索引排序
edit索引排序
edit在Elasticsearch中创建新索引时,可以配置每个分片内的段如何排序。默认情况下,Lucene不应用任何排序。index.sort.*设置定义了应使用哪些字段对每个段内的文档进行排序。
允许对包含嵌套对象的映射应用索引排序,只要index.sort.*设置中不包含嵌套字段。
例如,以下示例展示了如何在一个字段上定义排序:
PUT my-index-000001
{
"settings": {
"index": {
"sort.field": "date",
"sort.order": "desc"
}
},
"mappings": {
"properties": {
"date": {
"type": "date"
}
}
}
}
也可以通过多个字段对索引进行排序:
PUT my-index-000001
{
"settings": {
"index": {
"sort.field": [ "username", "date" ],
"sort.order": [ "asc", "desc" ]
}
},
"mappings": {
"properties": {
"username": {
"type": "keyword",
"doc_values": true
},
"date": {
"type": "date"
}
}
}
}
索引排序支持以下设置:
-
index.sort.field -
用于对索引进行排序的字段列表。
仅允许使用具有
doc_values的boolean、numeric、date和keyword字段。 -
index.sort.order -
每个字段要使用的排序顺序。 order 选项可以具有以下值:
-
asc: 升序 -
desc: 降序。
-
-
index.sort.mode -
Elasticsearch 支持对多值字段进行排序。 mode 选项控制选择哪个值来对文档进行排序。 mode 选项可以具有以下值:
-
min: 选择最小值。 -
max: 选择最大值。
-
-
index.sort.missing -
missing 参数指定如何处理缺少该字段的文档。 missing 值可以具有以下值:
-
_last: 没有该字段值的文档将排在最后。 -
_first: 没有该字段值的文档将排在最前。
-
索引排序只能在索引创建时定义一次。不允许在现有索引上添加或更新排序。索引排序还会在索引吞吐量方面产生成本,因为文档必须在刷新和合并时进行排序。在激活此功能之前,您应该测试其对应用程序的影响。
搜索请求的提前终止
edit默认情况下,Elasticsearch 中的搜索请求必须访问与查询匹配的每个文档,以检索按指定排序排序的顶部文档。 尽管当索引排序和搜索排序相同时,可以限制每个分段应访问的文档数量,以检索全局排名前 N 的文档。 例如,假设我们有一个按时间戳字段排序的事件索引:
PUT events
{
"settings": {
"index": {
"sort.field": "timestamp",
"sort.order": "desc"
}
},
"mappings": {
"properties": {
"timestamp": {
"type": "date"
}
}
}
}
您可以搜索最近的10个事件,使用:
GET /events/_search
{
"size": 10,
"sort": [
{ "timestamp": "desc" }
]
}
Elasticsearch 会检测到每个分段的顶部文档已经在索引中排序,并且只会比较每个分段的第一个 N 个文档。 与查询匹配的其余文档会被收集起来以计算结果的总数,并构建聚合。
如果你只寻找最近的10个事件,并且对匹配查询的文档总数不感兴趣,你可以将track_total_hits设置为false:
这次,Elasticsearch不会尝试计算文档的数量,并且一旦每个分段收集到N个文档,就能够终止查询。
聚合将收集所有匹配查询的文档,无论track_total_hits的值如何
使用索引排序来加速连接
edit索引排序可以用于组织Lucene文档ID(不要与_id混淆),以便使合取(a AND b AND …)更高效。为了提高效率,合取依赖于这样一个事实:如果任何子句不匹配,那么整个合取就不匹配。通过使用索引排序,我们可以将不匹配的文档放在一起,这将有助于高效地跳过不匹配合取的大范围文档ID。
这个技巧只适用于低基数字段。一个经验法则是,你应该首先对那些既具有低基数又经常用于过滤的字段进行排序。排序顺序(asc 或 desc)并不重要,因为我们只关心将匹配相同子句的值放在一起。
例如,如果您正在为待售汽车建立索引,按燃油类型、车身类型、品牌、注册年份和最后按里程数排序可能会很有趣。