如何处理关联关系
- 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
的值是可以自己根据业务需求自己设定的