最近一个半月都在搞SparkStreaming+Hbase+Redis+ES相关的实时流项目开发,其中重度使用了ElasticSearch做为一个核心业务的数据存储,因此这段时间更新文章较少,如今开发基本完事,接下来的会写几篇有关ElastiSearch的使用心得。java
大多数时候咱们使用es都是用来存储业务比较简单的数据,好比日志log类居多,就算有一些有主外键关联的数据,咱们也会提早join好,而后放入es中存储。mongodb
的确,扁平化后的数据存入索引,不管是写入,更新,查询都比较简单。可是有一些业务却无法扁平化后存储。好比咱们此次的业务数据。因为业务自己比较复杂,先看下数据实体模型。json
总共是三层模型,能够看到User(用户)包含多个Quest(题目),每一个题目又包含多个Kp(知识点),其中User,Quest,Kp都是一个实体类,能够包含多个属性,按照es的字段类型应该叫作object类型,先说说为何不能扁平化处理在写入索引,由于一旦扁平化其实只有统计知识点相关的聚合才是正确的,若想统计题目和人的一些聚合指标有些是查不出来的,由于一旦扁平前2级数据会被冗余放大好多倍,致使计算指标会出现问题。常规的count+distinct能够出来,可是一些sum指标就不对了,会多算冗余数据的和,并且无法再减出去,若是想作可能须要屡次查询才能搞定,理想状况下,一次查询就能搞定大部分查询或聚合 因此只有嵌套设计才能贴合真实的数据模型,换作关系型数据须要三张表,用mongodb也能够可是查询+聚合就没有es这么强大和高效微信
三层嵌套的好处就是贴合实际的数据实体模型,可是带来的弊端也很是明显,对深层嵌套数据的删除,修改比较麻烦,虽然也能作到,可是每一层的数据量越大,性能可能就越低,因此嵌套方案,适合存储和查询多级嵌套数据,且更新和删除操做少的业务状况,尽可能没有修改和删除。app
es的嵌套查询和聚合支持都比较完善,而且支持嵌套反转查询。嵌套数据的添加可使用script脚本方式来完成,直接将java的bean给转换完为json提交便可。性能
下面来看下动态mapping+嵌套类型设置,一个模板以下:设计
{ "order": 0, "template": "work*", "settings": { "index": { "number_of_replicas": "0", "number_of_shards": "3" } }, "mappings": { "_default_": { "dynamic_templates": [ { "nested_kps": { "mapping": { "type": "nested" }, "path_match": "quests.kps" } }, { "nested_quests": { "mapping": { "type": "nested" }, "match": "quests" } }, { "string_fields": { "mapping": { "index": "not_analyzed", "type": "string" }, "match": "*", "match_mapping_type": "string" } }, { "message": { "mapping": { "index": "analyzed", "type": "string" }, "match": "message", "match_mapping_type": "string" } }, { "date_fields": { "mapping": { "doc_values": true, "type": "date" }, "match": "*", "match_mapping_type": "date" } }, { "float_fields": { "mapping": { "doc_values": true, "type": "float" }, "match": "*", "match_mapping_type": "float" } }, { "double_fields": { "mapping": { "doc_values": true, "type": "double" }, "match": "*", "match_mapping_type": "double" } }, { "integer_fields": { "mapping": { "doc_values": true, "type": "integer" }, "match": "*", "match_mapping_type": "integer" } }, { "long_fields": { "mapping": { "doc_values": true, "type": "long" }, "match": "*", "match_mapping_type": "long" } } ], "_all": { "enabled": false } } }, "aliases": {} }
嵌套类型的关键词是nested,若是一个类型是nested,就至关因而设置了Java里面的List是一个集合对象list,能够有多个同一种类型的实体类数据,每一个数据里面还能够有本身的嵌套类型或其余类型,上面的动态mapping里面数据类型设置各个类型的定义,而且根据path设置了嵌套的动态mapping设置。这样以来就至关于设置了三层嵌套。3d
到此咱们应该能理解嵌套模型的定义和使用场景了,下篇会给出如何插入数据和使用script追加数据。日志
有什么问题能够扫码关注微信公众号:我是攻城师(woshigcs),在后台留言咨询。 技术债不能欠,健康债更不能欠, 求道之路,与君同行。code