在 NEST 中,如何根据术语列表动态构建查询?

in NEST, how do I dynamically build a query from a list of terms?

假设我的用户提供了我收集到 array/list 中的搜索词列表,现在我想使用 MatchPhrase 将这些 OR-wise 组合成一个 NEST 查询。我该怎么做? (单个)搜索词的代码如下所示:

var search = client.Search<ElasticRequirement>(s => s
.Query(q =>
    q.MatchPhrase(m => m.OnField(f => f.Title).Query(term.ToLower()).Slop(slop))
    || q.MatchPhrase(m => m.OnField(f => f.Description).Query(text).Slop(slop))
    )
   .LowercaseExpandedTerms()
   .Explain()
   .Query(q => q.Fuzzy(f => f.PrefixLength(1).OnField(c => c.Title).OnField(c => c.Description)))
);

很好,但我需要为提供的每个搜索词应用一次相同的 MatchPhrase 过滤器。非常感谢任何帮助。

您可以使用 bool should 表达式来动态构建查询。我将在下面提供完整的解决方案。使用适当的参数调用 BuildQuery() 方法。

ISearchResponse<ElasticRequirement> BuildQuery(IElasticClient client, IEnumerable<string> terms, int slop)
{
    return client.Search<ElasticRequirement>(s => s
        .Query(q => q
            .Bool(b => b
                .Should(terms.Select(t => BuildPhraseQueryContainer(q, t, slop)).ToArray())))
        .LowercaseExpandedTerms()
        .Explain()
        .Query(q => q.Fuzzy(f => f.PrefixLength(1).OnField(c => c.Title).OnField(c => c.Description))));
}

QueryContainer BuildPhraseQueryContainer(QueryDescriptor<ElasticRequirement> qd, string term, int slop)
{
    return qd.MatchPhrase(m => m.OnField(f => f.Title).Query(term.ToLower()).Slop(slop)) ||
        qd.MatchPhrase(m => m.OnField(f => f.Description).Query(term.ToLower()).Slop(slop));
}

对于 terms = {"term1", "term2", "term3"}slop = 0,将由我的代码构建的 Elasticsearch 搜索 JSON 命令如下:

{
  "explain": true,
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "should": [
              {
                "match": {
                  "title": {
                    "type": "phrase",
                    "query": "term1",
                    "slop": 0
                  }
                }
              },
              {
                "match": {
                  "description": {
                    "type": "phrase",
                    "query": "term1",
                    "slop": 0
                  }
                }
              }
            ]
          }
        },
        {
          "bool": {
            "should": [
              {
                "match": {
                  "title": {
                    "type": "phrase",
                    "query": "term2",
                    "slop": 0
                  }
                }
              },
              {
                "match": {
                  "description": {
                    "type": "phrase",
                    "query": "term2",
                    "slop": 0
                  }
                }
              }
            ]
          }
        },
        {
          "bool": {
            "should": [
              {
                "match": {
                  "title": {
                    "type": "phrase",
                    "query": "term3",
                    "slop": 0
                  }
                }
              },
              {
                "match": {
                  "description": {
                    "type": "phrase",
                    "query": "term3",
                    "slop": 0
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}

您可以调整此代码,使所有 match 命令都在同一个 should 节点下。我会把它留给你去弄清楚:)