1、elasticsearch 对 text 类型进行排序
排序的过程实质是对字段原始内容排序的过程,这个过程中倒排索引无法发挥作用,需要用到正排索引,也就是通过文档id 和字段可以快速得到字段原始内容。
es对此提供了2中实现方式:
- fielddata默认禁用;
- doc values 默认启用,除了text 类型。
fielddata 和 doc values对比如下:
对比 | fielddata | docvalues |
---|---|---|
创建时机 | 搜索时即时创建 | 索引时创建,与倒排索引创建时机一致 |
创建位置 | jvm heap | 磁盘 |
优点 | 不会占用额外的磁盘资源 | 不会占用 heap 内存 |
缺点 | 文档过多时,即时创建会花费过多时间,占用过多的heap 内存 | 减慢索引的速度(io过多),占用额外的磁盘资源 |
fielddata 介绍:
- fielddata默认是关闭的。
- 此时字符串是按照分词后的term 排序,往往结果很难符合预期;
- 一般是在对分词做聚合分析的时候开启。
- 语法如下:
PUT testindex/_mapping
{
"doc": {
"properties": {
"name": {
"type": "text",
"fielddata": true
}
}
}
}
docvalues 介绍:
- docvalues是默认启用的,可以在创建索引的时候关闭;
- 但是不能像fielddata一样随时开启,当再次开启时,需要做reindex 操作
2、分页与遍历
(一)from+size
- 基本使用不做介绍。
- 深度分页问题。页数越深,处理文档越多,占用内存越多,耗时越长。尽量避免深度分页,es通过 index.max_result_window参数限定最多到10000条数据。
(二)scroll
- 遍历文档集的api,以快照的方式来避免深度分页的问题;
- scroll不能用来做实时搜索,因为数据不是实时的。(因为它取的是某个时刻数据的快照,最新的数据进不来)
- 尽量不要使用复杂的sort 条件,使用 _doc 最高效。
(三)search after
- 避免深度分页的性能问题,提供实时的下一页文档获取功能;
- 缺点是不能使用from 参数,即不能指定页数;
- 只能下一页,不能上一页。
(四)应用场景
类型 | 场景 |
---|---|
from+size | 需要实时获取顶部的部分文档,且需要自由翻页。 |
scroll | 需要全部的文档,如导出所有数据的功能,不需要实时,不需要自由翻页。 |
search after | 需要全部的文档,需要实时,但不需要自由翻页。 |
3、nested 排序
DSL如下:
GET test/_search
{
"query": {
"nested": {
"path": "clientInfo",
"query": {
"nested": {
"path": "clientInfo.requestInfo",
"query": {
"match": {
"clientInfo.requestInfo.uri": "hello"
}
}
}
}
}
},
"sort": [
{
"common.time": {
"nested": {
"path": "common"
},
"order": "desc"
}
}
]
}
JAVA代码如下:
transportClient.prepareSearch("index").setTypes("doc").setQuery(queryBuilder).setPreference(preference)
.addSort(SortBuilders.fieldSort("common.time").setNestedSort(new NestedSortBuilder("common")).order(SortOrder.DESC))
.setSize(size).setFrom(from).execute().actionGet();
参考:
官网nested排序