淺談ElasticSearch的嵌套存儲模型



最近一個半月都在搞SparkStreaming+Hbase+Redis+ES相關的實時流項目開發,其中重度使用了ElasticSearch作為一個核心業務的數據存儲,所以這段時間更新文章較少,現在開發基本完事,接下來的會寫幾篇有關ElastiSearch的使用心得。

大多數時候我們使用es都是用來存儲業務比較簡單的數據,比如日志log類居多,就算有一些有主外鍵關聯的數據,我們也會提前join好,然后放入es中存儲。

的確,扁平化后的數據存入索引,無論是寫入,更新,查詢都比較簡單。但是有一些業務卻沒法扁平化后存儲。比如我們這次的業務數據。由於業務本身比較復雜,先看下數據實體模型。

image

總共是三層模型,可以看到User(用戶)包含多個Quest(題目),每個題目又包含多個Kp(知識點),其中User,Quest,Kp都是一個實體類,可以包含多個屬性,按照es的字段類型應該叫做object類型,先說說為什么不能扁平化處理在寫入索引,因為一旦扁平化其實只有統計知識點相關的聚合才是正確的,若想統計題目和人的一些聚合指標有些是查不出來的,因為一旦扁平前2級數據會被冗余放大好多倍,導致計算指標會出現問題。常規的count+distinct可以出來,但是一些sum指標就不對了,會多算冗余數據的和,而且沒法再減出去,如果想做可能需要多次查詢才能搞定,理想情況下,一次查詢就能搞定大部分查詢或聚合 所以只有嵌套設計才能貼合真實的數據模型,換做關系型數據需要三張表,用mongodb也可以但是查詢+聚合就沒有es這么強大和高效

三層嵌套的好處就是貼合實際的數據實體模型,但是帶來的弊端也非常明顯,對深層嵌套數據的刪除,修改比較麻煩,雖然也能做到,但是每一層的數據量越大,性能可能就越低,所以嵌套方案,適合存儲和查詢多級嵌套數據,且更新和刪除操作少的業務情況,盡量沒有修改和刪除。

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設置。這樣以來就相當於設置了三層嵌套。

到此我們應該能理解嵌套模型的定義和使用場景了,下篇會給出如何插入數據和使用script追加數據。



有什么問題可以掃碼關注微信公眾號:我是攻城師(woshigcs),在后台留言咨詢。 技術債不能欠,健康債更不能欠, 求道之路,與君同行。

輸入圖片說明


 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com