淺談ElasticSearch的嵌套存儲模型

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

大多數時候咱們使用es都是用來存儲業務比較簡單的數據,好比日誌log類居多,就算有一些有主外鍵關聯的數據,咱們也會提早join好,而後放入es中存儲。mongodb

的確,扁平化後的數據存入索引,不管是寫入,更新,查詢都比較簡單。可是有一些業務卻無法扁平化後存儲。好比咱們此次的業務數據。因爲業務自己比較複雜,先看下數據實體模型。json

image

總共是三層模型,能夠看到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

輸入圖片說明

相關文章
相關標籤/搜索