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

时间:2013-10-25 13:27:15

标签: elasticsearch nest

根据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分析器的定义很重要,因为地址字段没有在查询中使用,但如果有人想看到它,可以包含它。

1 个答案:

答案 0 :(得分:13)

这实际上是NEST中的一个错误

NEST如何帮助翻译布尔查询的前提:

NEST允许您使用运算符重载来轻松创建详细的bool查询/过滤器,例如:

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

现在,bug出现在你的情况中你有这个

bool(should=term1, term2, minimum_should_match=2) || term3 NEST确定OR操作的两端只包含should子句,并且它们将它们连接在一起,这将给第一个布尔查询的minimum_should_match参数赋予不同的含义。

我刚推出了一个修复程序,这将在下一个版本0.11.8.0

中修复

感谢您抓住这个!