首页 > 解决方案 > 弹性搜索在 NEST 中重新创建查询不起作用

问题描述

我试图从 Kibana dev 重新创建查询到 NEST,但它没有给我相同的结果。

我在 Kibana 中运行的查询完美地返回 1 个结果

这是我的 Kibana 查询:

GET /cats/_doc/_search
{   
"query":{
    "bool" : {     
        "minimum_should_match" :3,
        "should": [
           {"term" : { "name" : "cats" }},
           {"term" : { "name" : "are" }},
           {"term" : { "name" : "craze" }}

         ]
      }
   }
}

当我在 NEST 中创建查询时,它不返回任何结果,除非我将 minimum_should_match更改为 1(然后返回 2 个结果)

这是我的 NEST 查询:

        string[] tmp = "Cats are craze".ToLower().Split(new string[] { " " }, StringSplitOptions.None);

        var cats = ElasticMain.Search<dynamic>(s => s.From(from).Size(20).Query(
                  q => q.Bool(
                      b => b.MinimumShouldMatch(tmp.Length).Should(
                          l => l.Terms(
                              t => t.Name("name").Field("name").Terms(tmp)))

               )));

我究竟做错了什么?

标签: elasticsearchnest

解决方案


您在 NEST 中构建的查询与在 Kibana 中构建的查询不同;前者使用一个terms查询,而后者term在一个bool查询should子句中使用三个查询。这两个查询结合 minimum should match 的语义是不同的。

NEST 中的相同查询是

var client = new ElasticClient();

string[] tmp = "Cats are craze".ToLower().Split(new string[] { " " }, StringSplitOptions.None);
var from = 0;

var searchResponse = client.Search<dynamic>(s => s
    .From(from)
    .Size(20)
    .Query(q => q
        .Bool(b =>
        {
            b.MinimumShouldMatch(tmp.Length);
            var shouldQueries = 
                new List<Func<QueryContainerDescriptor<dynamic>, QueryContainer>>(tmp.Length);

            for (var i = 0; i < tmp.Length; i++)
            {
                var value = tmp[i];              
                shouldQueries.Add(qc => qc.Term(t => t
                    .Field("name")
                    .Value(value)
                ));
            }

            b.Should(shouldQueries);

            return b;
        })
    )
);

构建以下查询

{
  "from": 0,
  "query": {
    "bool": {
      "minimum_should_match": 3,
      "should": [
        {
          "term": {
            "name": {
              "value": "cats"
            }
          }
        },
        {
          "term": {
            "name": {
              "value": "are"
            }
          }
        },
        {
          "term": {
            "name": {
              "value": "craze"
            }
          }
        }
      ]
    }
  },
  "size": 20
}

should必须匹配的子句数等于minimum_should_match本例中的子句时,实际上等同于说它们都是must子句(没有 minimum_should_match)

var client = new ElasticClient();

string[] tmp = "Cats are craze".ToLower().Split(new string[] { " " }, StringSplitOptions.None);
var from = 0;

var searchResponse = client.Search<dynamic>(s => s
    .From(from)
    .Size(20)
    .Query(q => 
        tmp.Aggregate((QueryContainer)null, (qc, v) => qc && q.Term("name", v))
    )
);

它利用对 NEST 查询的运算符重载&&一起构建查询

{
  "from": 0,
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "name": {
              "value": "cats"
            }
          }
        },
        {
          "term": {
            "name": {
              "value": "are"
            }
          }
        },
        {
          "term": {
            "name": {
              "value": "craze"
            }
          }
        }
      ]
    }
  },
  "size": 20
}

推荐阅读