这是我参与8月更文挑战的第19天,活动详情查看:8月更文挑战
本Elasticsearch相关文章的版本为:7.4.2
prefix查询即前缀查询,查询field字段里包含特定前缀的文档。例如查询name字段以ri开头的文档。
测试数据:
POST /prefix_query_test/_doc/1
{
"name": "ridingroad"
}
POST /prefix_query_test/_doc/2
{
"name": "riseup"
}
查询姓名里以ri开头的文档:
GET /prefix_query_test/_search
{
"query": {
"prefix": {"name": "ri"}
}
}
返回的数据:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "prefix_query_test",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"name" : "ridingroad"
}
},
{
"_index" : "prefix_query_test",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"name" : "riseup"
}
}
]
}
}
前缀查询的过程:
为了支持前缀匹配,查询会做以下事情:
- 扫描词倒排索引并查找到第一个以
ri开始的词。 - 搜集关联的文档 ID 。
- 移动到下一条倒排索引。
- 如果这个词也是以
ri开头,查询跳回到第二步再重复执行,直到下一个词不以ri为止。
这对于小的例子当然可以正常工作,但是如果倒排索引中有数以百万的邮编都是以 ri 开头时,前缀查询则需要访问每个词然后计算结果!
前缀越短所需访问的词越多。如果我们要以 r 作为前缀而不是 ri ,那么就可能需要做千万次的匹配。
加速前缀查询
为了加快前缀查询,可以在设置mapping时候为需要进行前缀查询的字段设置index_prefixes。
使用index_prefixesmapping 参数可以加速前缀查询。如果启用,Elasticsearch 会在单独的字段中索引 2 到 5 个字符之间的前缀。这让 Elasticsearch 以更大的索引为代价但可以更有效地运行前缀查询(以空间换时间)。
min_chars 索引的最小前缀长度。必须大于 0,默认为 2。该值包含在内。
max_chars 索引的最大前缀长度。必须小于 20,默认为 5。该值包含在内。
PUT /prefix_test
{
"mappings": {
"properties": {
"name": {
"type": "text",
"index_prefixes": {
"min_chars": 2,
"max_chars": 5
}
}
}
}
}