ElasticSearch结合MultiMatch和Must

时间:2016-06-23 15:11:44

标签: c# json elasticsearch

所以我有这个对象模型:

string Name; // name of the person
int    Age; // age of the person
string CreatedBy; // operator who created person

我的查询听起来像这样:all documents WHERE Age > 40 AND CreatedBy == 'callum' AND Name contains 'll'

CreatedBy是必要的控制范围。

Age也是必要的(但不是安全问题)

Name是模糊的地方,因为这是用户查询的内容。类似于sort of contains

以下查询适用于前两部分:

"query": {
     "bool": {
         "must": [
            {
                "range": {
                   "age": {
                      "gt": 40
                   }
                }
            },
            {
                "match": {
                   "createdBy": "Callum"
                }   
            }
         ]
     }
   }

我尝试添加multi_match,因为最终可能会搜索NameAddress和其他信息。我无法理解它适合它的位置。

在我看来,嵌套查询会很有用。因此,首先过滤掉所有不相关的用户,然后过滤掉不相关的年龄。然后在相关领域做一些更模糊的匹配。

2 个答案:

答案 0 :(得分:0)

所以,答案并不简单。

首先,您需要为Compound Words创建分析器。

所以在.NET客户端看起来像:

this.elasticClient.CreateIndex("customer", p => p
    .Settings(s => s
        .Analysis(a => a
            .TokenFilters(t => t
                .NGram("bigrams_filter", ng => ng
                    .MaxGram(2)
                    .MinGram(2)))
        .Analyzers(al => al
            .Custom("bigrams", l => l
                .Tokenizer("standard")
                .Filters("lowercase", "bigrams_filter"))))));

this.elasticClient.Map<Person>(m => m
    .Properties(props => props
    .String(s => s
        .Name(p => p.Name)
        .Index(FieldIndexOption.Analyzed)
        .Analyzer("bigrams"))
    .String(s => s
        .Name(p => p.CreatedBy)
        .NotAnalyzed())
    .Number(n => n
        .Name(p => p.Age))));

这是所提供的第一个链接的直接翻译。现在这意味着所有名称都将被分解为他们的二元组表示:

卡勒姆

  1. CA
  2. LL
  3. 微米
  4. 然后您需要实际查询才能利用此功能。现在我喜欢这个,因为我们在name列上设置了索引,这意味着所有term个查询都可以包含部分单词,所以请以此为例(Sense query):

    GET customer/_search
    {
        "query": {
            "filtered": {
               "query": {
                "multi_match": {
                   "query": "ll",
                   "fields": ["name"]
                }
               },
               "filter": {
                   "bool": {
                           "must": [
                              {
                             "range": {
                                "age": {
                                   "gt": 40
                                }
                             }
                          },
                          {
                             "match": {
                                "createdBy": "Callum"
                             }
                          }
                       ]
                   }
               }
            }
        }
    }
    

    在这里,我们有一个过滤的查询。所以查询始终是第一个运行的(找不到文档引用它,但我已经读过了),这将是部分术语匹配。然后我们简单地过滤 - 这是在查询之后完成的 - 以获得我们需要的结果子集。

    因为ngrams分析器仅设置在name上,这是唯一将部分匹配的列。因此CreatedBy不会,因此我们会在结果周围获得安全

答案 1 :(得分:-1)

基本上你可以做的是将查询分成两个块:

"query": {
         "filter":{
            "bool":
            {
                "must":[
                    {
                        "range": {
                           "age": {
                              "gt": 40
                           }
                        }
                    }
                ]
            }
          },
         "query":{
            "bool": {
                "must": [
                    {
                      "multi_match" : {
                        "query":    "ll", 
                        "fields": [ "createdBy", "Address","Name" ] ,
                        "fuzziness":2
                      }
                    }             
                ]
            }
          }
       }

您可以在filter中使用条件filter来解决问题,然后使用过滤后的数据,您可以应用multi-match查询。我在filter中包含年龄的主要原因是因为您不需要执行任何类型的自由文本搜索,只需要检查静态值,您可以在must块中包含更多条件filter

您还可以查看本文,它可能会为您提供一些概述。

https://googleweblight.com/?lite_url=https://www.elastic.co/blog/found-optimizing-elasticsearch-searches&ei=EBaRAJDx&lc=en-IN&s=1&m=75&host=www.google.co.in&ts=1465153335&sig=APY536wHUUfGEjoafiVIzGx2H77aieiymw

希望它有所帮助!