推荐公众号
索引准备
索引mapping
PUT student
{
"mappings": {
"properties": {
"name":{
"type": "keyword"
},
"age":{
"type": "integer"
}
}
}
}
数据
PUT /student/doc/1
{ "name": "王-a" }
PUT /student/doc/2
{ "name": "王-b" }
PUT /student/doc/3
{ "name": "王-c" }
PUT /student/doc/4
{ "name": "王二a" }
。。。。。。。
查询条件
GET /studeng/_doc/_search
{
"query": {
"prefix": {
"name": "王-"
}
}
}
查询过程
name字段是keyword类型 不进行分词,每个name还是以它们精确值的方式存在于每个文档的索引中倒排索引中
在倒排索引中如下示例:
Term | doc ids |
---|---|
王一a | 1 |
王一b | 2 |
王一c | 3 |
王二a | 4 |
为了支持前缀匹配,查询会做以下事情: |
- 扫描词列表并查找到第一个以 王- 开始的词。
- 搜集关联的文档 ID 。
- 移动到下一个词。
- 如果这个词也是以 王-开头,查询跳回到第二步再重复执行,直到下一个词不以 王-为止。
这对于小的例子当然可以正常工作,但是如果倒排索引中有数以百万的邮编都是以王-开头时,前缀查询则需要访问每个词然后计算结果!
前缀越短所需访问的词越多。如果我们要以 王作为前缀而不是 王一 ,那么就可能需要做千万次的匹配。
wildcard 和 regexp
wildcard(通配符查询) 和 regexp(正则查询) 查询的工作方式与 prefix 查询完全一样,它们也需要扫描倒排索引中的词列表才能找到所有匹配的词,然后依次获取每个词相关的文档 ID ,与 prefix 查询的唯一不同是:它们能支持更为复杂的匹配模式。
这也意味着需要同样注意前缀查询存在性能问题,对有很多唯一词的字段执行这些查询可能会消耗非常多的资源,所以要避免使用左通配这样的模式匹配(如: *foo 或 .*foo 这样的正则式)。
参考文章
https://www.elastic.co/guide/cn/elasticsearch/guide/current/prefix-query.html