多字段搜索 (一) - 多个及单个查询字符串

2024-05-03 23:08

本文主要是介绍多字段搜索 (一) - 多个及单个查询字符串,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

多字段搜索(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

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


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

这篇关于多字段搜索 (一) - 多个及单个查询字符串的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/957857

相关文章

MySQL字符串转数值的方法全解析

《MySQL字符串转数值的方法全解析》在MySQL开发中,字符串与数值的转换是高频操作,本文从隐式转换原理、显式转换方法、典型场景案例、风险防控四个维度系统梳理,助您精准掌握这一核心技能,需要的朋友可... 目录一、隐式转换:自动但需警惕的&ld编程quo;双刃剑”二、显式转换:三大核心方法详解三、典型场景

MySQL中between and的基本用法、范围查询示例详解

《MySQL中betweenand的基本用法、范围查询示例详解》BETWEENAND操作符在MySQL中用于选择在两个值之间的数据,包括边界值,它支持数值和日期类型,示例展示了如何使用BETWEEN... 目录一、between and语法二、使用示例2.1、betwphpeen and数值查询2.2、be

C#实现将Excel工作表拆分为多个窗格

《C#实现将Excel工作表拆分为多个窗格》在日常工作中,我们经常需要处理包含大量数据的Excel文件,本文将深入探讨如何在C#中利用强大的Spire.XLSfor.NET自动化实现Excel工作表的... 目录为什么需要拆分 Excel 窗格借助 Spire.XLS for .NET 实现冻结窗格(Fro

MyBatis-Plus使用动态表名分表查询的实现

《MyBatis-Plus使用动态表名分表查询的实现》本文主要介绍了MyBatis-Plus使用动态表名分表查询,主要是动态修改表名的几种常见场景,文中通过示例代码介绍的非常详细,对大家的学习或者工作... 目录1. 引入依赖2. myBATis-plus配置3. TenantContext 类:租户上下文

MySQL基本表查询操作汇总之单表查询+多表操作大全

《MySQL基本表查询操作汇总之单表查询+多表操作大全》本文全面介绍了MySQL单表查询与多表操作的关键技术,包括基本语法、高级查询、表别名使用、多表连接及子查询等,并提供了丰富的实例,感兴趣的朋友跟... 目录一、单表查询整合(一)通用模版展示(二)举例说明(三)注意事项(四)Mapper简单举例简单查询

MySQL 数据库进阶之SQL 数据操作与子查询操作大全

《MySQL数据库进阶之SQL数据操作与子查询操作大全》本文详细介绍了SQL中的子查询、数据添加(INSERT)、数据修改(UPDATE)和数据删除(DELETE、TRUNCATE、DROP)操作... 目录一、子查询:嵌套在查询中的查询1.1 子查询的基本语法1.2 子查询的实战示例二、数据添加:INSE

springboot+mybatis一对多查询+懒加载实例

《springboot+mybatis一对多查询+懒加载实例》文章介绍了如何在SpringBoot和MyBatis中实现一对多查询的懒加载,通过配置MyBatis的`fetchType`属性,可以全局... 目录springboot+myBATis一对多查询+懒加载parent相关代码child 相关代码懒

Java中的随机数生成案例从范围字符串到动态区间应用

《Java中的随机数生成案例从范围字符串到动态区间应用》本文介绍了在Java中生成随机数的多种方法,并通过两个案例解析如何根据业务需求生成特定范围的随机数,本文通过两个实际案例详细介绍如何在java中... 目录Java中的随机数生成:从范围字符串到动态区间应用引言目录1. Java中的随机数生成基础基本随

在DataGrip中操作MySQL完整流程步骤(从登录到数据查询)

《在DataGrip中操作MySQL完整流程步骤(从登录到数据查询)》DataGrip是JetBrains公司出品的一款现代化数据库管理工具,支持多种数据库系统,包括MySQL,:本文主要介绍在D... 目录前言一、登录 mysql 服务器1.1 打开 DataGrip 并添加数据源1.2 配置 MySQL

Go语言中如何进行数据库查询操作

《Go语言中如何进行数据库查询操作》在Go语言中,与数据库交互通常通过使用数据库驱动来实现,Go语言支持多种数据库,如MySQL、PostgreSQL、SQLite等,每种数据库都有其对应的官方或第三... 查询函数QueryRow和Query详细对比特性QueryRowQuery返回值数量1个:*sql