一尘不染

&&和||怎么做 在NEST中构建查询?

elasticsearch

根据http://nest.azurewebsites.net/concepts/writing-
queries.html,&&和|| 可以使用NEST库将运算符组合为两个查询,以与Elastic Search进行通信。

我设置了以下查询:

var ssnQuery = Query<NameOnRecordDTO>.Match(
                q => q.OnField(f => f.SocialSecurityNumber).QueryString(nameOnRecord.SocialSecurityNumber).Fuzziness(0)
            );

然后将其与Bool查询结合,如下所示:

var result = client.Search<NameOnRecordDTO>(
     body => body.Query(
          query => query.Bool(
              bq => bq.Should(
                  q => q.Match(
                     p => p.OnField(f => f.Name.First)
                         .QueryString(nameOnRecord.Name.First).Fuzziness(fuzziness)
                  ),
                  q => q.Match(p => p.OnField(f => f.Name.Last)
                         .QueryString(nameOnRecord.Name.Last).Fuzziness(fuzziness)
                  )
              ).MinimumNumberShouldMatch(2)
          ) || ssnQuery
     )
);

我认为此查询的意思是,如果SocialSecurityNumber匹配项或Name.FirstName.Last字段都匹配,则记录应包括在结果中。

当我使用对QueryString的调用中使用的nameOnRecord对象的以下数据执行此查询时:

"socialSecurityNumber":"123456789",
    "name" : {
      "first":"ryan",          
    }

结果是拥有SSN的人123456789,以及有姓氏的人ryan

如果我|| ssnQuery从上面的查询中删除,则会得到所有人的名字为“ ryan”。

随着|| ssnQuery到位,下面的查询:

{
    "socialSecurityNumber":"123456789",
    "name" : {
      "first":"ryan",
      "last": "smith"
    }        
}

我似乎得到了SSN 123456789的人以及名字为“ ryan”或姓氏为“ smith”的人。

因此,添加似乎并没有达到|| ssnQuery我预期的效果,我也不知道为什么。

这是有关对象的索引的定义:

"nameonrecord" : {
    "properties": {      
        "name": {
            "properties": {
                "name.first": {
                    "type": "string"
                 },
                 "name.last": {
                    "type": "string"
                 }
             }   
        },
        "address" : {
            "properties": {
                "address.address1": {
                    "type": "string",
                     "index_analyzer": "address",
                     "search_analyzer": "address"
                 },
                "address.address2": {
                    "type": "string",
                    "analyzer": "address"
                 },
                 "address.city" : {
                    "type": "string", 
                    "analyzer": "standard"
                 },
                 "address.state" : {
                    "type": "string",
                    "analyzer": "standard"
                 },
                 "address.zip" : {
                    "type" : "string",
                    "analyzer": "standard"
                 }
            }   
        },                
        "otherName": {
           "type": "string"
        },
        "socialSecurityNumber" : {
           "type": "string"   
        },
        "contactInfo" : {
           "properties": {
                "contactInfo.phone": {
                    "type": "string"
                },
                "contactInfo.email": {
                    "type": "string"
                }
            }
        }                
     }   
}

我认为address分析器的定义并不重要,因为查询中未使用地址字段,但是如果有人想查看它,可以将其包括在内。


阅读 213

收藏
2020-06-22

共1个答案

一尘不染

这实际上是NEST中的错误

NEST如何帮助转换布尔查询的先驱:

NEST允许您使用运算符重载轻松创建详细的布尔查询/过滤器,即:

term && term 将导致:

bool
    must
        term
        term

天真的实现会重写

term && term && term

bool
    must
        term
        bool
            must
                term
                term

正如您可以想象的那样,查询变得更加复杂,NEST可以发现这些并将它们结合在一起,从而变得非常笨拙

bool
    must 
        term
        term
        term

同样term && term && term && !term简单地变成:

bool
    must 
        term
        term
        term
    must_not
        term

现在,如果在前面的示例中您像这样直接传递booleanquery

bool(must=term, term, term) && !term

它仍然会生成相同的查询。当NEST should看到播放中的布尔描述符仅由组成时,NEST也将与进行同样的操作should clauses。这是因为boolquery并没有完全遵循您希望从编程语言中获得的布尔逻辑。

总结一下:

term || term || term

变成

bool
    should
        term
        term
        term

term1 && (term2 || term3 || term4) 不会成为

bool
    must 
        term1
    should
        term2
        term3
        term4

这是因为布尔查询一旦具有must子句,就应该开始作为促进因素。因此,在前面的内容中,您可能会得到仅包含term1此内容的结果,这在严格的布尔输入意义上显然不是您想要的。

为此,NEST将此查询重写为

bool 
    must 
        term1
        bool
            should
                term2
                term3
                term4

现在,这个错误开始起作用的地方就是您的情况

bool(should=term1, term2, minimum_should_match=2) || term3NEST标识OR操作的两侧仅包含应该子句,它将它们连接在一起,这将给minimum_should_match第一个布尔查询的参数赋予不同的含义。

我只是为此推送了一个修复程序,它将在下一个版本中修复 0.11.8.0

感谢您抓住这个!

2020-06-22