浅谈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

输入图片说明

相关文章
相关标签/搜索