ES存儲document時,會根據數據對應的field類型建立對應的索引。通常來說只創建倒排索引,倒排索引是爲了搜索而存在的,但如果對數據進行排序、聚合、過濾等操作時,再使用倒排索引就明顯不適合了。這個時候就需要在ES中創建正排索引(doc values)。doc values保存在磁盤中,如果OS Cache系統緩存的空間足夠大,ES會緩存doc values,因此性能還是很不錯的。
問: 爲什麼說倒排索引不適合做聚合、排序等操作?
答: 比如有數據如下:
{
“name” : “張三”,
“remark” : “java開發工程師”,
"_id": 1
}
{
“name” : “李四”,
“remark” : “java架構工程師”,
"_id": 2
}
爲remark字段創建倒排索引:
Term | Doc |
---|---|
java | 1,2 |
開發 | 1 |
架構 | 2 |
工程師 | 1,2 |
如果在倒排索引的基礎上進行聚合,那麼到底是根據java進行聚合呢、還是根據開發或者架構來聚合呢?不難發現,用哪一個都不合適。排序也是如此。倒排索引因分詞得到了許多好處,但也因此留下了弊端。
所以,爲了應對這種不需要分詞的需求和場景,ES設計了正排索引Doc values。Doc values不會對字段作任何分詞處理,皆保留原值。
正排索引的大致結構如下:
Doc values | Values |
---|---|
Doc1 | java開發工程師 |
Doc2 | java架構工程師 |
ES會根據document中每個字段是否分詞,有選擇性的實現字段對應的倒排索引或正排索引(Doc values)。
比如,如果字段類型爲keyword,long,date,那麼這些類型修飾的字段一定會有正排索引(Doc values)。
比如,如果字段類型爲text,則只會有倒排索引,不會主動創建正排索引。
如果想在同一個字段中,既實現正排索引,又實現倒排索引,只需要使用fielddata即可,實現方式如下:
若遇到聚合、排序等需求時,ES使用test_field.keyword,若遇到搜索需求時,ES使用test_field。
{
"mappings": {
"type": {
"properties": {
"test_field": {
"type": "text",
"analyzer": "standard",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
}
}