ElasticSearch-为什么不能使用_id排序

在这里插入图片描述

场景

在elasticsearch中我们通常有查询、聚合、排序的需求,而在es中默认使用相关度评分来排序,但是我们也可以指定字段排序。
类似于MySQL中的select * from test where name=“张三” order by id;
在ES-8.x版本中通常我们只会创建需要的字段,而_id做为元字段会自动生成。
但是如果使用该_id排序时会报错(如下)

{
“content”: “{“error”:{“root_cause”:[{“type”:“illegal_argument_exception”,“reason”:“Fielddata access on the _id field is disallowed, you can re-enable it by updating the dynamic cluster setting: indices.id_field_data.enabled”}],“type”:“search_phase_execution_exception”,“reason”:“all shards failed”,“phase”:“query”,“grouped”:true,“failed_shards”:[{“shard”:0,“index”:“dtk_follow”,“node”:“gUZyKR3ERwKlPhLSCOPWcw”,“reason”:{“type”:“illegal_argument_exception”,“reason”:“Fielddata access on the _id field is disallowed, you can re-enable it by updating the dynamic cluster setting: indices.id_field_data.enabled”}}],“caused_by”:{“type”:“illegal_argument_exception”,“reason”:“Fielddata access on the _id field is disallowed, you can re-enable it by updating the dynamic cluster setting: indices.id_field_data.enabled”,“caused_by”:{“type”:“illegal_argument_exception”,“reason”:“Fielddata access on the _id field is disallowed, you can re-enable it by updating the dynamic cluster setting: indices.id_field_data.enabled”}}},“status”:400}”,
“status”: “400 Bad Request”,
“status_code”: 400
}

根据提示解决办法很简单,通过设置参数(id_field_data.enabled)就可以让_id排序
那么为什么默认_id是不允许排序的呢?让我们一起来分析下

ElasticSearch中_id分析

首先从_id本身来看

  • _id字段是一个物理字段,用于唯一标识每个文档。而在ES中 默认的_id 并不会生成 Doc Values。
  • 在ES中,如果字段没有使用Doc Values的数据结构来存储,那么该字段就不允许被排序或聚合。

那么Doc Values又是什么呢

  • 在ES中,Doc Values 就是一种列式存储结构,默认情况下,在索引创建一个文档的字段时(非text属性),也会创建对应的Doc Values。
  • Doc Values其实就是我们所说的正排索引,基于段生成且不可变,同时是序列化到磁盘的。

这里还有一个概念需要介绍一下:
因为文档值被序列化到磁盘,所以我们可以充分利用操作系统的内存。当 working set 远小于节点的可用内存,系统会所有的Doc Values值保存在操作系统的内存中,使得其读写十分高速; 当其远大于可用内存,操作系统会根据需要从磁盘读取Doc Values然后选择性的放到分页缓存中。

为了完整的理解这个问题,我们先引入下一个概念

正排索引和倒排索引

正排索引:就是我们刚刚说的Doc Values,在ES中主要用于排序、聚合等,默认是不分词,不支持text。
倒排索引:就是ES中最大的特点,由倒排表、词项字典、词项索引组成,全文检索非常高效。
通过一张图来看下两者的区别
1.png
现在看就很明显了,由于数据结构的不同,使用正排索引来排序将是非常高效的。而使用倒排索引排序就相当于全表扫描了。所以在ES中,默认禁止非Doc Values存储的数据排序或聚合。
与Doc Values相关联的概念还有fielddata

ES中fielddata

fielddata也是ES中的一种数据结构,与Doc Values不同,它由JVM管理,常驻于JVM Heap中。由于filedData是存储在内存中,所以一些高基数字段在生成 filedData 是会消耗大量的内存
其实fielddata和Doc Values的主要区别是:

  • Doc Values是落盘的正排索引,需要排序或聚合时加载到内存就行了
  • fielddata是对非正排索引需要排序或聚合时在内存中建立正排索引,fielddata 的构建和管理发生在 JVM Heap中
  • 而且fielddata是常驻内存的,JVM垃圾回收并不会回收此区域的内存,官方解释如下

2.png

结论

现在就很通透了。
_id是ES的默认字段,并且非Doc Values属性,所以默认是不允许被排序或聚合的。
但是ES也专门对_id设置了参数:indices.id_field_data.enabled,设置为true就可以使用_id排序
而针对索引内自己创建的字段,要不就在创建索引的时候开启fielddata(如下)
3.png
要不就单独开启(如下)
4.png

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
下面是一个使用elasticsearch_dsl库的Python示例,用于执行基本的搜索操作: ```python # 导入所需的库和模块 from elasticsearch_dsl import connections, Search, Q # 创建与Elasticsearch集群的连接 connections.create_connection(hosts=['192.168.214.131'], port=9200, http_auth="elastic:ellischen") # 创建一个Search对象,并指定索引名称 search = Search(using=connections.get_connection(), index='books') # 构建查询条件 query = Q('match_all') # 设置查询条件 search = search.query(query) # 设置排序方式 search = search.sort('_id') # 执行搜索操作 response = search.execute() # 输出搜索结果 for hit in response: print(hit) ``` 这个示例首先使用`create_connection`方法创建与Elasticsearch集群的连接。然后,它创建一个`Search`对象,指定要搜索的索引名称。接下来,使用`Q`对象来构建查询条件,这里使用了`match_all`查询,表示匹配所有文档。然后,使用`sort`方法设置排序方式,这里按`_id`字段进行升序排序。最后,使用`execute`方法执行搜索操作,并迭代搜索结果进行输出。 请注意,你需要根据你的实际环境修改连接参数和索引名称。还可以根据需要添加其他的查询条件和排序方式。 希望这个示例对你有帮助!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [python elasticsearch_dsl search_after翻页](https://blog.csdn.net/weixin_43632687/article/details/126404629)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值