多字段搜索(Multifield Search)

本文翻译自官方指南的Multifield Search一章。

查询很少是只拥有一个match查询子句的查询。我们经常需要对一个或者多个字段使用相同或者不同的查询字符串进行搜索,这意味着我们需要将多个查询子句和它们得到的相关度分值以一种有意义的方式进行合并。

也许我们正在寻找一本名为战争与和平的书,它的作者是Leo Tolstoy。也许我们正在使用"最少应该匹配(Minimum Should Match)"来搜索ES中的文档。另外我们也可能会寻找拥有名为John而姓为Smith的用户。

在本章中我们会讨论一些构建多字段搜索的工具,以及如何根据你的实际情况来决定使用哪种方案。

多个查询字符串(Multiple Query Strings)

处理字段查询最简单的方法是将搜索词条对应到特定的字段上。如果我们知道战争与和平是标题,而Leo Tolstoy是作者,那么我们可以简单地将每个条件当做一个match子句,然后通过bool查询将它们合并:

GET /_search
{
"query": {
"bool": {
"should": [
{ "match": { "title": "War and Peace" }},
{ "match": { "author": "Leo Tolstoy" }}
]
}
}
}

bool查询采用了一种"匹配越多越好(More-matches-is-better)"的方法,因此每个match子句的分值会被累加来得到文档最终的_score。匹配两个子句的文档相比那些只匹配一个子句的文档的分值会高一些。

当然,你并不是只能使用match子句:bool查询可以包含任何其他类型的查询,包括其它的bool查询。我们可以添加一个子句来指定我们希望的译者:

GET /_search
{
"query": {
"bool": {
"should": [
{ "match": { "title": "War and Peace" }},
{ "match": { "author": "Leo Tolstoy" }},
{ "bool": {
"should": [
{ "match": { "translator": "Constance Garnett" }},
{ "match": { "translator": "Louise Maude" }}
]
}}
]
}
}
}

我们为什么将译者的查询子句放在一个单独的bool查询中?所有的4个match查询都是should子句,那么为何不将译者的查询子句和标题及作者的查询子句放在同一层次上呢?

答案在于分值是如何计算的。bool查询会运行每个match查询,将它们的分值相加,然后乘以匹配的查询子句的数量,最后除以所有查询子句的数量。相同层次的每个子句都拥有相同的权重。在上述查询中,bool查询中包含的译者查询子句只占了总分值的三分之一。如果我们将译者查询子句放到和标题及作者相同的层次上,就会减少标题和作者子句的权重,让它们各自只占四分之一。

设置子句优先级

上述查询中每个子句占有三分之一的权重也许并不是我们需要的。相比译者字段,我们可能对标题和作者字段更有兴趣。我们对查询进行调整来让标题和作者相对更重要。

在所有可用措施中,我们可以采用的最简单的方法是boost参数。为了增加titleauthor字段的权重,我们可以给它们一个大于1boost值:

GET /_search
{
"query": {
"bool": {
"should": [
{ "match": {
"title": {
"query": "War and Peace",
"boost": 2
}}},
{ "match": {
"author": {
"query": "Leo Tolstoy",
"boost": 2
}}},
{ "bool": {
"should": [
{ "match": { "translator": "Constance Garnett" }},
{ "match": { "translator": "Louise Maude" }}
]
}}
]
}
}
}

以上的title和k字段的boost值为2。 嵌套的bool查询自居的默认boost值为k。

通过试错(Trial and Error)的方式可以确定"最佳"的boost值:设置一个boost值,执行测试查询,重复这个过程。一个合理boost值的范围在110之间,也可能是15。比它更高的值的影响不会起到很大的作用,因为分值会被规范化(Normalized)

单一查询字符串(Single Query String)

bool查询是多字段查询的中流砥柱。在很多场合下它都能很好地工作,特别是当你能够将不同的查询字符串映射到不同的字段时。

问题在于,现在的用户期望能够在一个地方输入所有的搜索词条,然后应用能够知道如何为他们得到正确的结果。所以当我们把含有多个字段的搜索表单称为高级搜索(Advanced Search)时,是有一些讽刺意味的。高级搜索虽然对用户而言会显得更"高级",但是实际上它的实现方式更简单。

对于多词,多字段查询并没有一种万能的方法。要得到最佳的结果,你需要了解你的数据以及如何使用恰当的工具。

了解你的数据

当用户的唯一输入就是一个查询字符串时,你会经常碰到以下三种情况:

最佳字段(Best fields)

当搜索代表某些概念的单词时,例如"brown fox",几个单词合在一起表达出来的意思比单独的单词更多。类似title和body的字段,尽管它们是相关联的,但是也是互相竞争着的。文档在相同的字段中应该有尽可能多的单词(译注:搜索的目标单词),文档的分数应该来自拥有最佳匹配的字段。

多数字段(Most fields)

一个用来调优相关度的常用技术是将相同的数据索引到多个字段中,每个字段拥有自己的分析链(Analysis Chain)。

主要字段会含有单词的词干部分,同义词和消除了变音符号的单词。它用来尽可能多地匹配文档。

相同的文本可以被索引到其它的字段中来提供更加精确的匹配。一个字段或许会包含未被提取词干的单词,另一个字段是包含了变音符号的单词,第三个字段则使用shingle来提供关于单词邻近度(Word Proximity)的信息。

以上这些额外的字段扮演者signal的角色,用来增加每个匹配的文档的相关度分值。越多的字段被匹配则意味着文档的相关度越高。

跨字段(Cross fields)

对于一些实体,标识信息会在多个字段中出现,每个字段中只含有一部分信息:

  • Person:first_name 和 last_name
  • Book:titleauthor 和 description
  • Address:streetcitycountry 和 postcode

此时,我们希望在任意字段中找到尽可能多的单词。我们需要在多个字段中进行查询,就好像这些字段是一个字段那样。


以上这些都是多词,多字段查询,但是每种都需要使用不同的策略。我们会在本章剩下的部分解释每种策略。

[Elasticsearch] 多字段搜索 (一) - 多个及单个查询字符串的更多相关文章

  1. [Elasticsearch2.x] 多字段搜索 (一) - 多个及单个查询字符串 <译>

    多字段搜索(Multifield Search) 本文翻译自官方指南的Multifield Search一章. 查询很少是只拥有一个match查询子句的查询.我们经常需要对一个或者多个字段使用相同或者 ...

  2. Elasticsearch 多字段搜索

    查询很少是对一个字段做 match 查询,通常都是一个 query 查询多个字段,比如一个 doc 有 title.content.pagetag 等文本字段,要在这些字段查询含多个 term 的 q ...

  3. elasticsearch多字段搜索

    https://blog.csdn.net/Ricky110/article/details/78888711 多字段搜索多字符串查询boost 参数 “最佳” 值,较为简单的方式就是不断试错,比较合 ...

  4. Elasticsearch 全字段搜索_all,query_string查询,不进行分词

    最近在使用ELasitcsearch的时候,需要用到关键字搜索,因为是全字段搜索,就需要使用_all字段的query_string进行搜索. 但是在使用的时候,遇到问题了.我们的业务并不需要分词,我在 ...

  5. [Elasticsearch] 多字段搜索 (六) - 自定义_all字段,跨域查询及精确值字段

    自定义_all字段 在元数据:_all字段中,我们解释了特殊的_all字段会将其它所有字段中的值作为一个大字符串进行索引.尽管将所有字段的值作为一个字段进行索引并不是非常灵活.如果有一个自定义的_al ...

  6. [Elasticsearch] 多字段搜索 (五) - 以字段为中心的查询

    以字段为中心的查询(Field-centric Queries) 上述提到的三个问题都来源于most_fields是以字段为中心(Field-centric),而不是以词条为中心(Term-centr ...

  7. [Elasticsearch] 多字段搜索 (三) - multi_match查询和多数字段 <译>

    multi_match查询 multi_match查询提供了一个简便的方法用来对多个字段执行相同的查询. NOTE 存在几种类型的multi_match查询,其中的3种正好和在“了解你的数据”一节中提 ...

  8. [Elasticsearch] 多字段搜索 (三) - multi_match查询和多数字段

    multi_match查询 multi_match查询提供了一个简便的方法用来对多个字段执行相同的查询. NOTE 存在几种类型的multi_match查询,其中的3种正好和在"了解你的数据 ...

  9. [Elasticsearch] 多字段搜索 (二) - 最佳字段查询及其调优

    最佳字段(Best Fields) 假设我们有一个让用户搜索博客文章的网站,就像这两份文档一样: PUT /my_index/my_type/1 { "title": " ...

随机推荐

  1. cookie与session的区别,你真的明白吗?

    当我们访问网页时,http是属于无状态的,为什么呢?接下来由我慢慢讲解,在cookie的到来之前,你第一次访问页面的时候和最后一次访问页面服务器是不知道的,不知道那一次访问的页面是你.当用户登录的时候 ...

  2. ArrayList调用remove(int index)抛出UnsupportedOperationException问题分析以及解决记录

    使用Arrays转数组成为List后,不能调用add(...)和remove(...)方法,此时如果调用就会抛出UnsupportedOperationException异常 原因 其实Arrays. ...

  3. JavaScript--文本框中只允许输入数字的操作(其他字符不显示)

    在web网页中,尤其是某些提交表单操作,需要验证文本框输入内容,本文利用文本框键盘事件和事件对象,对文本框只允许输入数字方法进行总结. 1.键盘事件 keydown ---->键盘按下事件    ...

  4. 基于socketserver模块实现并发的套接字(tcp、udp)

    tcp服务端:import socketserver class MyHandler(socketserver.BaseRequestHandler): def handle(self): #通信循环 ...

  5. ElasticSearch 安装配置

    1.   Elasticsearch5.5.2安装 1.1.Elasticsearch安装步骤 #安装之前需安装java 环境,并配置JAVA_HOME环境变量 #直接下载Elasticsearch- ...

  6. AtCoder AGC028-F:Reachable Cells

    越来越喜欢AtCoder了,遍地都是神仙题. 题意: 给定一个\(N\)行\(N\)列的迷宫,每一个格子要么是障碍,要么是空地.每一块空地写着一个数码.在迷宫中,每一步只允许向右.向下走,且只能经过空 ...

  7. 数据库 MySQL part2

    表记录的操作 增 1.插入一条记录 语法:insert [into] tab_name (field1,filed2,.......) values (value1,value2,.......); ...

  8. OSI七层模型加协议

    OSI七层网络模型 TCP/IP四层概念模型 对应网络协议 应用层(Application) 应用层 HTTP.TFTP, FTP, NFS, WAIS.SMTP 表示层(Presentation) ...

  9. 【MVC】 小问题

    [MVC] 小问题 1. url 传参中文乱码 : encodeURIComponent 转码 2. RedirectToAction 重定向 : ajax 调用无效, 直接 url 访问有效 3. ...

  10. 【数据结构】 List 简单实现

    public class XList<T> : IEnumerable, IEnumerator { #region List 简单实现 /// <summary> /// 存 ...