es全文检索论文_es深入搜索之全文检索

本文探讨了Elasticsearch的全文搜索,包括查询与结果的相关性、分析过程,重点介绍了match查询、多词查询、权重调整以及相关度计算原理。通过示例详细解释了如何在Elasticsearch中实现高效、精准的全文检索。
摘要由CSDN通过智能技术生成

我们之前介绍过结构化搜索的简单使用,接下来,我们来看怎样在全文字段中搜索最相关的文档。

全文搜索包括两个最重要的方面:

1. 查询与结果的相关性,并根据相关性对结果进行排名。

2. 分析,将数据转化为有区别的、规范化的的过程。

所有的查询都或多或少的会进行相关度计算,但不是所有的查询都会有分析阶段,文本查询可以分为两个部分:

1. 基于词项的查询,如 term 或 fuzzy 这样的查询是没有分析阶段的。他们对单个词项进行操作。

2. 基于全文的查询,比如match, 它们会先了解字段映射的信息,判断字段是否被分词,是否是日期还是数字等, 再根据映射信息,构建要查询的词项列表,根据列表进行查询。

1. 匹配查询

匹配查询 match 是个核心查询。无论需要查询什么字段, match 查询都应该会是首选的查询方式。使用方式如下:

GET /index/type/_search

{

"query": {

"match": {

"filed": "value"

}

}

}

es执行上列步骤的过程如下:

检查字段类型。

如果该字段是(analyzed )已分析的字段,这意味这查询字符串也应该被分析。

分析查询字符串。

使用相关分词器对查询字符串进行分词,然后根据分词后的结果进行term查询。

查找匹配文档。

根据相关算法进行评分,然后排序。

2.多词查询

如果一次只能搜索一个词语,那么全文搜索会不太灵活,幸运的是 match 也支持多词查询 。

GET /index/type/_search

{

"query": {

"match": {

"fileld": "words1 words2"

}

}

}

以上查询其实先后执行了两次 term 查询,使用 bool 进行包含,然后将结果进行合并返回。

以上查询其实会导致出现不相关的结果,我们只想搜索包含words1 和 words2 的文档,而不是or 的结果。match 查询还可以接受 operator 操作符作为输入参数,默认情况下该操作符是or 。

"match": {

"filed": {

"query": "words1 words2",

"operator": "and"

}

}

这种操作还是有些不妥,在 and 和 or 中间选择太过绝对,如果用户给出了5个词项,我们想只要满足其中4 个 就表示匹配,match 也提供了minimum_should_match参数,他是一个最小匹配参数,我们可以控制满足的词项超过改值则表示匹配,最好是使用百分比,因为你也不知道用户提供了多少个词项。该参数的设置非常灵活,完整的信息参考文档,请看https://www.elastic.co/guide/en/elasticsearch/reference/5.6/query-dsl-minimum-should-match.html#query-dsl-minimum-should-match

"query": {

"match": {

"title": {

"query": "quick brown dog",

"minimum_should_match": "75%"

}

}

}

3. 提高权重

如果我们使用 bool 查询黑色、大屏、手机,其中should 语句匹配得越多表示文档的相关度越高,但是我们想要手机所占的权重比较大,内容包括手机的文档排名靠前,可以使用boost设置相对权重,注意是相对权重,默认是1。

"query": {

"bool": {

"should": [{

"content": "手机",

"boost": 3

},

{

"content": "大屏",

"boost": 1

},

{

"content": "黑色",

"boost": 1

}]

}

}

4. 被破坏的相关度

在说相关度被破坏的原因之前,我们先看看es对于相关度是如何计算的

es 的相似度算法被定义为检索词频率/反向文档频率, TF/IDF ,包括以下内容:

检索词频率 : 检索词在该字段出现的频率, 出现频率越高,相关性也越高。

反向文档频率 : 每个检索词在索引中出现的频率,频率越高,相关性越低。

字段长度准则 : 字段的长度是多少,长度越长,相关性越低。

有时,我们索引了一些文档,然后检索发现有些相关度较低的返回排名靠前?

出现上述原因的情况是因为es由于性能原因,不会计算所有索引该文档的节点的IDF,比如我们索引了10个文档, 其中6个文档中包含 foo ,而由于es是分布式的,一个索引会被分为多个分片,有可能分片一包含的5 个文档,有 4 个包含foo, 而另外一个在分片二中,所以会导致结果有差异。

在实际应用中,不会出现该问题,因为本局和全局的IDF差异会随着文档数量的增加逐渐降低。如果想要自己处理该问题,可以在搜索请求之后增加?search_type=dfs_query_then_fetch,他会使得es先计算各个分片的 IDF, 然后在求出全局的 IDF, 生产环境中不要使用。因为只要有足够的数据就可以使得差异减少。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值