阅读 34

大数据利器Elasticsearch之prefix前缀查询

这是我参与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"
        }
      }
    ]
  }
}
复制代码

前缀查询的过程:

为了支持前缀匹配,查询会做以下事情:

  1. 扫描词倒排索引并查找到第一个以 ri 开始的词。
  2. 搜集关联的文档 ID 。
  3. 移动到下一条倒排索引。
  4. 如果这个词也是以 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
        }    
      }
    }
  }
}
复制代码
文章分类
后端
文章标签