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

rya*_*all 3 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)
            );
Run Code Online (Sandbox Code Playgroud)

然后将其与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
     )
);
Run Code Online (Sandbox Code Playgroud)

我认为这个查询意味着如果SocialSecurityNumber匹配,或者两个Name.FirstName.Last字段都匹配,那么记录应该包含在结果中.

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

"socialSecurityNumber":"123456789",
    "name" : {
      "first":"ryan",          
    }
Run Code Online (Sandbox Code Playgroud)

结果是SSN的人123456789,以及任何有名字的人ryan.

如果我|| ssnQuery从上面的查询中删除,我会得到名字为'ryan'的每个人.

随着|| ssnQuery到位和以下查询:

{
    "socialSecurityNumber":"123456789",
    "name" : {
      "first":"ryan",
      "last": "smith"
    }        
}
Run Code Online (Sandbox Code Playgroud)

我似乎找到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"
                }
            }
        }                
     }   
}
Run Code Online (Sandbox Code Playgroud)

我不认为address分析器的定义很重要,因为地址字段没有在查询中使用,但如果有人想看到它,可以包括它.

Mar*_*man 13

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

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

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

term && term 将导致:

bool
    must
        term
        term
Run Code Online (Sandbox Code Playgroud)

一个天真的实现将重写

term && term && term

bool
    must
        term
        bool
            must
                term
                term
Run Code Online (Sandbox Code Playgroud)

正如你可以想象的那样,这变得笨拙很快,查询变得越复杂,NEST就可以发现它们并将它们连接起来

bool
    must 
        term
        term
        term
Run Code Online (Sandbox Code Playgroud)

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

bool
    must 
        term
        term
        term
    must_not
        term
Run Code Online (Sandbox Code Playgroud)

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

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

它仍然会生成相同的查询.当NEST should看到播放中的布尔描述符只包含时,NEST也会这样做should clauses.这是因为boolquery并不完全遵循您对编程语言所期望的相同布尔逻辑.

总结后者:

term || term || term

bool
    should
        term
        term
        term
Run Code Online (Sandbox Code Playgroud)

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

bool
    must 
        term1
    should
        term2
        term3
        term4
Run Code Online (Sandbox Code Playgroud)

这是因为一旦布尔查询具有must子句,就应该开始充当提升因子.所以在之前你可以得到只包含term1这个结果的结果显然不是你想要的严格布尔意义上的输入.

因此,NEST将此查询重写为

bool 
    must 
        term1
        bool
            should
                term2
                term3
                term4
Run Code Online (Sandbox Code Playgroud)

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

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

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

感谢您抓住这一个!