最近一個半月都在搞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