ElasticSearch设置index=False,为什么还能查询

648 阅读4分钟

我是左耳朵梵高,北理工毕业,曾在阿里巴巴中间件团队任职。沉浸软件行业十余年,相信技术能改变世界。译有《你真的会写代码吗?》
坚持输出技术干货,职场心得和读书感悟。欢迎关注公众号「左耳朵梵高」,和我一起持续学习,终生成长。

最近使用ElasticSearch时,有一个字段的Mapping设置了index = False,竟然能被查询到,很不解。后面花了点时间,把原因弄清楚了,今天把这个小知识点分享给大家,避免后面踩坑。

背景

事情的起因是这样的,因业务需要,系统中的文件地址从http升级为https协议,我用下面的REST API来订正ES中的数据:

POST my_index/_update_by_query
{
  "script": {
    "lang": "painless",
    "inline": "ctx._source.url = ctx._source.url.replace('http', 'https')"
  },
  "query": {
    "exists": {
      "field": "url"
    }
  }
}

执行完发现更新了0条数据。不对呀,明明是有数据的。把query单独拿出来执行一下,果然是0条。

POST my_index/_search
{
  "query": {
    "exists": {
      "field": "url"
    }
  }
}

难道DSL语句写错了?这么简单不应该呀。换成update_time字段可以查询出来数据。说明,查询语句没错,根据我的经验,应该是字段的配置导致的。于是查了下Mapping:

"update_time" : {
  "type" : "long",
  "index" : false
},
"url" : {
  "type" : "text",
  "index" : false
}

这下明白了,url设置了index = False,没有索引,当然查询不出来了。不对,等等,update_time也是index = False,为什么它能查出来?

答案就在官方文档中

我们知道,在ElasticSearch中,index控制字段是否被索引,即创建倒排索引。如果有倒排索引,能够被搜索。 字段默认index = True。如果显式设置index=False,字段不会被索引,也不能被查询。

上面的知识,大家比较熟悉。但其实关于index的配置,官方文档中还有下面一段话:

这段话有3个关键信息:

  1. index控制字段是否要索引。
  2. 默认是True
  3. 对于特定类型的字段,即使设置了 index = False,仍然可以通过doc_values进行查询。

这些特定字段类型包括:

  • Numeric:数值类型
  • Date:日期类型
  • Boolean:布尔类型
  • IP:IP 类型
  • Geo_point:地理点类型
  • Keyword:关键字类型

上面的第3点就是原因所在!update_time是数字类型,即使index=False,因为doc values开启(默认开启),依然可以检索。

什么是doc values

上面还提到了一个概念doc values,什么是doc values?
众所周知,ES索引采用倒排索引的数据结构,能实现高效的全文检索。一提到ES,大家就能想到倒排索引。

事实上,ES要应对各种数据处理场景,包括全文检索、排序、聚合、数据迁移、重建索引等。不同场景需要的数据结构也不相同。

当一个新文档进入ES时,ES为它创建不同的数据结构,保存在索引中。倒排索引只是其中一种。看一下官方对ES索引数据结构的介绍:

A Lucene index is made of several components: an inverted index, a bkd tree, a column store (doc values), a document store (stored fields) and term vectors.

除了大家都知道的倒排索引,还有bkd tree,column store,document store和term vectors。

我们今天不用太关注这些术语,接下来我会以ES的Mapping配置为例,对常用配置进行说明。

创建ES时,Mapping中有一些选项和上面提到的底层数据结构是一一对应的,比如:

  • index:是否创建倒排索引。默认True。
  • _source:是否保留原始文档。默认True。
  • doc_value:是否创建doc_value。默认True。

倒排索引提供全文检索能力,但无法排序和聚合数据。doc_value则弥补了该能力。它采用了列存储方式,保存原始字段值,可以实现高效的排序和聚合。doc_value默认开启,如果确认某个字段不需要排序、聚合或在Script脚本中使用,可以禁用doc_value来节省磁盘空间。但很多的ES功能都使用到了doc_value进行加速,因此不建议关闭。

和倒排索引相比,通过doc_value进行查询效率比较低,因为需要对整个索引进行全扫描。

参考: