【问题标题】:Elastic Search multi match gets wrong result弹性搜索多重匹配得到错误的结果
【发布时间】:2020-03-10 05:49:29
【问题描述】:

我正在向 Elastic Search 发送查询以查找具有与查询匹配的字段的所有段。 我们正在实现一个“免费搜索”,用户可以编写他想要的任何文本,我们构建一个查询,搜索这个文本会抛出所有的段字段。 其一个(或多个)字段具有此文本的每个段都应返回

例如:

我想获取名称为“tony lopez”的所有片段。 每个段都有一个“first_name”字段和一个“last_name”字段。

我们的服务构建的查询:

  "multi_match" : {
    "query": "tony lopez",
    "type": "best_fields"
    "fields": [],
    "operator": "OR"
  }

使用此查询的 Elastic 的结果是包含“first_name”字段“tony”和“last_name”字段“lopez”的段,但也是“first_name”字段为“joe”和“last_name”时的段是“托尼”。

在这种类型的查询中,我只想接收其名称为“tony (first_name) lopez (last_name)”的段

我该如何解决这个问题?

【问题讨论】:

  • 为问题添加更多上下文总是更好。如果您指定映射和一些示例数据会很棒
  • 正确的结果是什么?
  • 感谢您的回答!每个字段提到的数据类型都是“文本”。我们实施了“免费搜索”,您可以插入任何文本并接收该文本在其字段之一中找到的段。正确的结果只有名字是“tony”和姓氏是“lopez”的片段。

标签: java jquery json elasticsearch


【解决方案1】:

希望我不会过早下结论,但如果您只想获得 tony 和 lopez 作为名字和姓氏,请使用:

GET my_index/_search
{
  "query": { 
   "bool": {
     "must": [
       {
         "match": {
           "first": "tony"
         }
       },
       {
         "match": {
           "last": "lopez"
         }
       }
     ]
   }
  }
}

但是,如果您的一个索引文档包含例如 tony s 作为名字,上面的查询也会返回它。

为什么? firstname 是 text 数据类型

索引全文值的字段,例如电子邮件正文或产品描述。对这些字段进行分析,即通过分析器将字符串转换为单个术语的列表,然后再编入索引。

More Details

如果您通过kibana 运行此查询:

POST my_index/_analyze
{
  "field": "first", 
  "text": ["tony s"]
}

您会看到tony s 被分析为两个标记tony 和s。

通过分析器将字符串转换为单个术语的列表(tony 作为术语,s 作为术语)。

这就是为什么上面的查询在结果中返回tony s,它匹配tony。

如果您只想获得 tony 和 lopez 完全匹配,那么您应该使用以下查询:

GET my_index/_search
{
  "query": { 
   "bool": {
     "must": [
       {
         "term": {
           "first.keyword": {
             "value": "tony"
           }
         }
       },
       {
         "term": {
           "last.keyword": {
             "value": "lopez"
           }
         }
       }
     ]
   }
  }
}

Read about keyword datatype

更新

试试这个查询 - 这与我的 tony s 示例不是完全相同的问题,如果您有一个包含名字 lopez 和姓氏 tony 的文档,它会找到它。

GET my_index/_search
{
  "query": { 
   "multi_match": {
     "query": "tony lopez",
     "fields": [],
     "type": "cross_fields",
     "operator":"AND",
     "analyzer":   "standard"

   }
  }
}

cross_fields 类型对于需要匹配多个字段的结构化文档特别有用。例如,当查询 first_name 和 last_name 字段中的“Will Smith”时,最佳匹配可能是一个字段中包含“Will”而另一个字段中包含“Smith”

cross fields

希望对你有帮助

【讨论】:

  • 感谢您的回答!与您的建议一样,我们正在实施“免费搜索”,您可以在其中插入任何文本并接收该文本在其中一个字段中找到的片段。因此,我对弹性的查询只是查询本身,没有指定我正在搜索哪些字段。我将编辑我的问题并添加此关键信息。
  • @RoyLeibovitz 查看我的更新 - 向下滚动直到看到 UPDATE
  • 最新解决方案的问题是名字和姓氏字段被分成2个不同的字段。因此,当我发送此查询时,我得到 0 个结果..
  • 我不明白。请分享您的映射。
  • @RoyLeibovitz 我刚刚看到您正在使用自定义分析器,cross_fields 使用相同的分析器处理字段,就好像它们是一个大字段一样。我更新了我的查询(添加了 "analyzer": "standard"),因此查询将对所有字段应用相同的分析器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多