
我是左耳朵梵高,北理工毕业,曾在阿里巴巴中间件团队任职。沉浸软件行业十余年,相信技术能改变世界。译有《你真的会写代码吗?》
坚持输出技术干货,职场心得和读书感悟。欢迎关注公众号「左耳朵梵高」,和我一起持续学习,终生成长。
最近使用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个关键信息:
- index控制字段是否要索引。
- 默认是
True。 - 对于特定类型的字段,即使设置了 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进行查询效率比较低,因为需要对整个索引进行全扫描。
参考: