如何處理關聯關係
- Kibana 目前暫時不支持 nested 類型和 parent/child 類型 ,在未來有可能會支持,在Kibana界面上展示數據的時候不是很友好
- 如果需要使用Kibana進行數據分析,在建模時需要對嵌套和父子類型進行取捨
避免過多字段
- 過多字段不好維護
- Mapping信息保存在Cluster State中,數據量過大,對集羣性能有影響(Cluster State信息需要和所有節點同步)
- 刪除或者修改數據需要reindex.
- 默認最大字段數是 1000,可以設置 index.mapping.total_fields.limt 限定最大字段數
- 生產環境儘量不要打開Dynamic Dynamic Mapping
- 考慮下這樣一個場景,
##索引數據,dynamic mapping 會不斷加入新增字段
PUT cookie_service/_doc/1
{
"url":"www.google.com",
"cookies":{
"username":"tom",
"age":32
}
}
PUT cookie_service/_doc/2
{
"url":"www.amazon.com",
"cookies":{
"login":"2019-01-01",
"email":"[email protected]"
}
}
我們的cookie字段使用了Dynamic=true
默認值,所以隨着寫入的數據越來越多,如果不對cookies字段的子字段進行限制的話,字段數會越來越多,會影響性能,
- 解決方案
#使用 Nested 對象,增加key/value
PUT cookie_service
{
"mappings": {
"dynamic": "strict",
"properties": {
"cookies": {
"type": "nested",
"properties": {
"name": {
"type": "keyword"
},
"dateValue": {
"type": "date"
},
"keywordValue": {
"type": "keyword"
},
"IntValue": {
"type": "integer"
}
}
},
"url": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
需要說明幾點的是:
- 設置
"dynamic": "strict"
阻止其他字段加入 - 通過name和dateValue, keywordValue, IntValue這樣的設計可以存儲任意的key-value
避免正則查詢
正則查詢的性能不夠好,前綴查詢屬於Term查詢
- 案例如下:
文檔中某個字段包含了Elasticsearch的版本信息,例如version: "7.1.0",現在我們需要查詢朱版本是7,次要版本是2的文檔,不要使用正則查詢
- 解決方案如下: 我們使用inner object 將幾個版本信息拆開存儲,
PUT softwares/
{
"mappings": {
"_meta": {
"software_version_mapping": "1.1"
},
"properties": {
"version": {
"properties": {
"display_name": {
"type": "keyword"
},
"hot_fix": {
"type": "byte"
},
"marjor": {
"type": "byte"
},
"minor": {
"type": "byte"
}
}
}
}
}
}
然後我們再使用查詢
POST softwares/_search
{
"query": {
"bool": {
"filter": [
{
"match":{
"version.marjor":7
}
},
{
"match":{
"version.minor":2
}
}
]
}
}
}
避免空值引起的聚合不準
- 首先我們先看一下示例
PUT ratings/_doc/1
{
"rating":5
}
PUT ratings/_doc/2
{
"rating":null
}
POST ratings/_search
{
"size": 0,
"aggs": {
"avg": {
"avg": {
"field": "rating"
}
}
}
}
# 查詢結果
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"avg" : {
"value" : 5.0
}
}
}
很明顯,我們查到了兩條數據,但是平均值是5,這個很難以理解,
- 解決方案,我們給null值設置一個默認值
PUT ratings
{
"mappings": {
"properties": {
"rating": {
"type": "float",
"null_value": 0
}
}
}
}
再次插入上面的數據,我們得到下面的結果
{
"took" : 5,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"avg" : {
"value" : 2.5
}
}
}
這樣就比較對了,當然null_value
的值是可以自己根據業務需求自己設定的