Elasticsearch 数据建模的一些建议
如何处理关联关系
- 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
的值是可以自己根据业务需求自己设定的
相关推荐
molong0 2020-08-06
YYDU 2020-06-21
katanaFlower 2020-06-21
newbornzhao 2020-09-14
做对一件事很重要 2020-09-07
renjinlong 2020-09-03
明瞳 2020-08-19
李玉志 2020-08-19
mengyue 2020-08-07
AFei00 2020-08-03
molong0 2020-08-03
wenwentana 2020-08-03
YYDU 2020-08-03
另外一部分,则需要先做聚类、分类处理,将聚合出的分类结果存入ES集群的聚类索引中。数据处理层的聚合结果存入ES中的指定索引,同时将每个聚合主题相关的数据存入每个document下面的某个field下。
sifeimeng 2020-08-03
心丨悦 2020-08-03
liangwenrong 2020-07-31
sifeimeng 2020-08-01
mengyue 2020-07-30