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排序