多值字段(Multivalue Fields)

在多值字段上使用短语匹配会产生古怪的行为:

PUT /my_index/groups/1
{
"names": [ "John Abraham", "Lincoln Smith"]
}

执行一个针对Abraham Lincoln的短语查询:

GET /my_index/groups/_search
{
"query": {
"match_phrase": {
"names": "Abraham Lincoln"
}
}
}

令人诧异的是,以上的这份文档匹配了查询。

即使Abraham以及Lincoln分属于name数组的两个人名中。

发生这个现象的原因在于数组在ES中的索引方式。

当John Abraham被解析时。它产生例如以下信息:

  • 位置1:john
  • 位置2:abraham

然后当Lincoln Smith被解析时。它产生了:

  • 位置3:lincoln
  • 位置4:smith

换言之,ES对以上数组分析产生的词条列表和解析单一字符串John Abraham Lincoln Smith时产生的结果是一样的。在我们的查询中。我们查询邻接的abraham和lincoln,而这两个词条在索引中确实存在而且邻接,因此查询匹配了。

幸运的是,有一个简单的方法来避免这样的情况。通过position_offset_gap參数,它在字段映射中进行配置:

DELETE /my_index/groups/ 

PUT /my_index/_mapping/groups
{
"properties": {
"names": {
"type": "string",
"position_offset_gap": 100
}
}
}

position_offset_gap设置告诉ES须要为数组中的每一个新元素设置一个偏差值。因此,当我们再索引以上的人名数组时,会产生例如以下的结果:

  • 位置1:john
  • 位置2:abraham
  • 位置103:lincoln
  • 位置104:smith

如今我们的短语匹配就无法匹配该文档了。由于abraham和lincoln之间的距离为100。你必需要加入一个值为100的slop的值才干匹配。

越近越好(Closer is better)

短语查询(Phrase Query)仅仅是简单地将不含有精确查询短语的文档排除在外,而邻近查询(Proximity Query) - 一个slop值大于0的短语查询 - 会将查询词条的邻近度也考虑到终于的相关度_score中。

通过设置一个像50或100这种高slop值,你能够排除那些单词过远的文档。可是也给予了那些单词邻近的文档一个更高的分值。

以下针对quick dog的邻近查询匹配了含有quick和dog的两份文档,可是给与了quick和dog更加邻近的文档一个更高的分值:

POST /my_index/my_type/_search
{
"query": {
"match_phrase": {
"title": {
"query": "quick dog",
"slop": 50
}
}
}
}
{
"hits": [
{
"_id": "3",
"_score": 0.75,
"_source": {
"title": "The quick brown fox jumps over the quick dog"
}
},
{
"_id": "2",
"_score": 0.28347334,
"_source": {
"title": "The quick brown fox jumps over the lazy dog"
}
}
]
}

使用邻近度来提高相关度

虽然邻近度查询(Proximity Query)管用,可是全部的词条都必须出如今文档的这一要求显的过于严格了。这个问题和我们在全文搜索(Full-Text
Search)
一章的精度控制(Controlling
Precision)
一节中讨论过的类似:假设7个词条中有6个匹配了,那么该文档或许对于用户而言已经足够相关了,可是match_phrase查询会将它排除在外。

相比将邻近度匹配作为一个绝对的要求。我们能够将它当做一个信号(Signal) - 作为众多潜在匹配中的一员,会对每份文档的终于分值作出贡献(參考多数字段(Most
Fields)
)。

我们须要将多个查询的分值累加这一事实表示我们应该使用bool查询将它们合并。

我们能够使用一个简单的match查询作为一个must子句。该查询用于决定哪些文档须要被包括到结果集中。能够通过minimum_should_match參数来去除长尾(Long tail)。

然后我们以should子句的形式加入很多其它特定查询。每一个匹配了should子句的文档都会添加其相关度。

GET /my_index/my_type/_search
{
"query": {
"bool": {
"must": {
"match": {
"title": {
"query": "quick brown fox",
"minimum_should_match": "30%"
}
}
},
"should": {
"match_phrase": {
"title": {
"query": "quick brown fox",
"slop": 50
}
}
}
}
}
}

毫无疑问我们能够向should子句中加入其他的查询,每一个查询都用来添加特定类型的相关度。

[Elasticsearch] 邻近匹配 (二) - 多值字段,邻近程度与相关度的更多相关文章

  1. [Elasticsearch] 邻近匹配 (一) - 短语匹配以及slop參数

    本文翻译自Elasticsearch官方指南的Proximity Matching一章. 邻近匹配(Proximity Matching) 使用了TF/IDF的标准全文搜索将文档,或者至少文档中的每一 ...

  2. ElasticSearch实战系列二: ElasticSearch的DSL语句使用教程---图文详解

    前言 在上一篇中介绍了ElasticSearch集群和kinaba的安装教程,本篇文章就来讲解下 ElasticSearch的DSL语句使用. ElasticSearch DSL 介绍 Elastic ...

  3. Elasticsearch: 权威指南 » 深入搜索 » 多字段搜索 » 多数字段 good

      跨字段实体搜索  » 多数字段编辑 全文搜索被称作是 召回率(Recall) 与 精确率(Precision) 的战场: 召回率 ——返回所有的相关文档:精确率 ——不返回无关文档.目的是在结果的 ...

  4. solr 通过【配置、多值字段、动态字段】来解决文本表达式查询精确到句子的问题

    一.Solr Multivalue field属性positionIncrementGap理解 分类:Lucene 2014-01-22 10:39阅读(3596)评论(0) 参考:http://ro ...

  5. Elasticsearch入门教程(二):Elasticsearch核心概念

    原文:Elasticsearch入门教程(二):Elasticsearch核心概念 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:ht ...

  6. Elasticsearch入门(二)

    基础概念 Elasticsearch有几个核心概念,从一开始理解这些概念会对整个学习过程有莫大的帮助. 接近实时(NRT) Elasticsearch是一个接近实时的搜索平台.这意味着,从索引一个文档 ...

  7. Elasticsearch: 权威指南 » 深入搜索 » 多字段搜索 » 多数字段 good

      跨字段实体搜索  » 多数字段编辑 全文搜索被称作是 召回率(Recall) 与 精确率(Precision) 的战场: 召回率 --返回所有的相关文档:精确率 --不返回无关文档.目的是在结果的 ...

  8. Elasticsearch学习笔记二

    PS:上一篇已经介绍了ES的一些基础概念以及单机版ES的安装,配置,本文主要介绍ES的集群管理,CRUD以及简单聚合查询. 集群管理 ES的集群部署起来也很方便,将单机版SCP复制几分,修改elast ...

  9. C#,如何程序使用正则表达式如何使用匹配的位置的结果修改匹配到的值

    程序代码使用正则表达式如何修改匹配到的值: 代码一: using System; using System.Text.RegularExpressions; public class Example ...

随机推荐

  1. JDBC+Servlet+jsp(增删查改)

    先在mysql新增数据库和表先,把下面的几句代码复制去到mysql运行就可以创建成功了!  创建数据库 create database jdbc01 character set utf8 collat ...

  2. CSS浮动(Float)

    定义 浮动会使元素向左或向右移动,其周围的元素也会重新排列: 浮动直到它的外边缘碰到包含框或者另一个浮动框才停止: 浮动之后的元素将围绕它,浮动之前的元素不变: 由于浮动框不在文档的普通流中,所以文档 ...

  3. Akka(36): Http:Client-side-Api,Client-Connections

    Akka-http的客户端Api应该是以HttpRequest操作为主轴的网上消息交换模式编程工具.我们知道:Akka-http是搭建在Akka-stream之上的.所以,Akka-http在客户端构 ...

  4. KVM管理平台openebula安装

    1.1opennebula控制台的安装 (如果要添加映像需要给200G以上给/var/lib/one,本文是共享/var/lib/one实现监控,用映像出创建虚拟机原理是从opennebula控制平台 ...

  5. python3随笔第一天

    1.python 语言没有{},注重书写格式,注重空格的使用,书写python程序一定要注意代码对齐,代码格式对齐是python程序书写的生命: 2.python 分支判断格式  if 条件 :  e ...

  6. ALTER TABLE SWITCH' statement failed. The table x' is partitioned while index 'x' is not partitioned.

    1.L_Monitoring有这么些字段,ID,Collecttime,PlateType,PlateNO以及其他一些这段.建立这个表的时候是个非分区表,其中ID是主键,并在Collecttime,P ...

  7. Win32 SDK 编程开始, 创建窗口, 消息的处理, 消息循环

    Windows SDK 编程的一般步骤为: 1. 注册窗口类, 使用到的结构 WNDCLASSEX, 函数 RegisterClassEx. 2. 创建窗口, 函数 CreateWindowEx. 3 ...

  8. python进阶------进程线程(三)

    python中的进程 1.multiprocessing模块 由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进 ...

  9. Python之作用域

    作用域测试例子: >>> a = 10 >>> def test(): ... a = 20 ... print a ... >>> a 10 & ...

  10. 72、django之简单验证码实现与form表单钩子函数补充

    本篇主要讲解简单的验证码实现,验证码使用基本都是找现成的组件来实现,用代码实现这个简单功能主要是了解了解验证码内部的实现. 本篇导航: 五位验证码图示 代码实现 登录验证 Form组件钩子函数补充 一 ...