本学习笔记基于ElasticSearch 7.10版本,旧版本已经废弃的查询功能暂时不做笔记,以后有涉及到再做补充。
参考官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.10/full-text-queries.html
一、match
match
会对查询语句进行分词,分词后,如果查询语句中的任何一个词项被匹配,则文档就会被索引到。
# 先查询两个不相关的关键字
GET books/_search
{
"query": {
"match": {
"name": "美术"
}
}
}
GET books/_search
{
"query": {
"match": {
"name": "计算机"
}
}
}
# 再合并查询两个关键字
GET books/_search
{
"query": {
"match": {
"name": "美术计算机"
}
}
}
单独查询美术和计算机时,查询到符合条件的文档数分别是 9 和 46 条。
合并查询时会对美术计算机进行分词,分词之后再去查询,只要文档中包含任意一个分词,就回返回文档,最后查询到符合条件的文档树正好是55条。
可以看到,分词后词项之间是 OR 的关系,如果想要修改,也可以通过 operator
改为 AND:
GET books/_search
{
"query": {
"match": {
"name": {
"query": "十一五计算机",
"operator": "and"
}
}
}
}
二、match_phrase
match_phrase
就是短语查询,也会对查询的关键字进行分词,但是它分词后有两个特点:
- 分词后的词项顺序必须和文档中词项的顺序一致
- 所有的词都必须出现在文档中
但是注意,这里直接使用前面十一五计算机短语,并不能查询到文档,因为分词之后,关键字之间还间隔这国家级规划教材:大学这些内容。
这种情况可以使用 slop
参数来指定关键字之间的距离,注意这个距离,不是指关键字之间间隔的字数,而是指它们之间的 position 位置的间隔。
什么是position ?
每份文档中的字段被分词器解析之后,解析出来的词项都包含一个 position 字段表示词项的位置。每份文档的 position 都从 0 开始,每个词项递增 1 。
使用ik分词器测试如下:
GET books/_analyze
{
"text": "普通高等教育“十一五”国家级规划教材:大学计算机基础",
"analyzer": "ik_max_word"
}
# 分词结果
{
"tokens" : [
...
{
"token" : "十一五",
"start_offset" : 7,
"end_offset" : 10,
"type" : "CN_WORD",
"position" : 4
},
{
"token" : "十一",
"start_offset" : 7,
"end_offset" : 9,
"type" : "CN_WORD",
"position" : 5
},
{
"token" : "五",
"start_offset" : 9,
"end_offset" : 10,
"type" : "CN_CHAR",
"position" : 6
},
{
"token" : "国家级",
"start_offset" : 11,
"end_offset" : 14,
"type" : "CN_WORD",
"position" : 7
},
{
"token" : "国家",
"start_offset" : 11,
"end_offset" : 13,
"type" : "CN_WORD",
"position" : 8
},
{
"token" : "级",
"start_offset" : 13,
"end_offset" : 14,
"type" : "CN_CHAR",
"position" : 9
},
{
"token" : "规划",
"start_offset" : 14,
"end_offset" : 16,
"type" : "CN_WORD",
"position" : 10
},
{
"token" : "教材",
"start_offset" : 16,
"end_offset" : 18,
"type" : "CN_WORD",
"position" : 11
},
{
"token" : "大学",
"start_offset" : 19,
"end_offset" : 21,
"type" : "CN_WORD",
"position" : 12
},
{
"token" : "计算机",
"start_offset" : 21,
"end_offset" : 24,
"type" : "CN_WORD",
"position" : 13
},
...
]
}
分词后十一五 最后出现的 position = 6 ,而 计算机 第一次出现的 position = 13,中间间隔了 6 个位置。所以只需要设置 slop
为 6 即可查询到文档:
GET books/_search
{
"query": {
"match_phrase": {
"name": {
"query": "十一五计算机",
"slop": 6
}
}
}
}
三、match_phrase_prefix
类似于match_phrase
查询,只不过这里多了一个通配符,match_phrase_prefix
将最后一个词项作为前缀去查询匹配,但是由于这种匹配方式效率较低,因此大家作为了解即可。
GET books/_search
{
"query": {
"match_phrase_prefix": {
"name": {
"query": "计",
"max_expansions": 1
}
}
}
}
这个查询过程,会自动进行词项匹配,会自动查找以 计 开始的词项,默认是 10 个,我们可以通过 max_expansions
控制值匹配的词项个数。例如以 计 开始的词项控制匹配个数为 1 、2 、3 时,匹配到的词项分别为 计分、计划、计算 。
注意,match_phrase_prefix
是针对分片级别的查询,每个分片匹配的词项可能不一致。我们现在练习创建的索引分片数为 1 ,所以使用起来并不会有什么问题。但是如果分片数大于 1 时,查询结果就可能有问题。
以match_phrase_prefix
为 1 ,分片数为 3 举例,可能会查询出 3 个匹配词项对应的文档:
分片数 | 匹配词项 | 文档数 |
---|---|---|
分片1 | 计分 | 2 |
分片2 | 计划 | 1 |
分片3 | 计算 | 46 |
四、multi_match
match
查询的升级版,可以指定多个查询域:
GET books/_search
{
"query": {
"multi_match": {
"query": "java",
"fields": ["name","info"]
}
}
}
这种查询方式还可以指定字段的权重:
GET books/_search
{
"query": {
"multi_match": {
"query": "java",
"fields": ["name^4","info"]
}
}
}
这个表示关键字出现在 name 中的权重是出现在 info 中权重的 4 倍。
五、query_string
query_string
是一种紧密结合 Lucene 的查询方式,在一个查询语句中可以用到 Lucene 的一些查询语法:
GET books/_search
{
"query": {
"query_string": {
"default_field": "name",
"query": "(十一五) AND (计算机)"
}
}
}
六、simple_query_string
这个是query_string
的升级,可以直接使用 +、|、- 代替 AND、OR、NOT 等。
注意: simple_query_string
使用 fields 来指定查询的字段,即使只指定一个字段,值也必须为数组类型:
GET books/_search
{
"query": {
"simple_query_string": {
"fields": ["name"],
"query": "(十一五) + (计算机)"
}
}
}
版权声明:
本文仅记录ElasticSearch学习心得,如有侵权请联系删除。
更多内容请访问原创作者:江南一点雨
版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: