赞
踩
1. 非规范化数据
比如mysql描述订单以及订单详情 : order(id, order_no, amount) -> order_detail(id, order_id, commodity, price) , 在关系型数据库中一个订单对应多个订单详情,详情表通过order_id与订单表关联。
那么在es中可以通过冗余数据描述这种关系, 索引如下:
- PUT order {
- "mappings": {
- "order": { --> 指定文档名(订单表)
- "properties": { --> 指定字段以及类型
- "id": {
- "type": "integer"
- },
- "order_no": {
- "type": "long"
- },
- "amount": {
- "type": "double"
- },
- "order_detail": { --> 描述订单详情
- "properties": {
- "id": {
- "type": "integer"
- },
- "order_id": {
- "type": "integer"
- },
- "commodity": {
- "type": "text"
- },
- "price": {
- "type": "double"
- }
- }
- }
- }
- }
- }
- }
该索引就是把订单以及订单详情冗余在一起。订单详情可以理解成java实体对象中的集合对象。
2. 父子文档关联
父子文档关联类似于join的操作,通过建立索引的时候描述文档之间的关系
父-子关系文档 在实质上类似于 nested model :允许将一个对象实体和另外一个对象实体关联起来。而这两种类型的主要区别是:在 nested objects 文档中,所有对象都是在同一个文档中,而在父-子关系文档中,父对象和子对象都是完全独立的文档。
父-子关系的主要作用是允许把一个 type 的文档和另外一个 type 的文档关联起来,构成一对多的关系:一个父文档可以对应多个子文档 。与 nested objects 相比,父-子关系的主要优势有:
更新父文档时,不会重新索引子文档。
创建,修改或删除子文档时,不会影响父文档或其他子文档。这一点在这种场景下尤其有用:子文档数量较多,并且子文档创建和修改的频率高时。
子文档可以作为搜索结果独立返回。
Elasticsearch 维护了一个父文档和子文档的映射关系,得益于这个映射,父-子文档关联查询操作非常快。但是这个映射也对父-子文档关系有个限制条件:父文档和其所有子文档,都必须要存储在同一个分片中。
父-子文档ID映射存储在 Doc Values 中。当映射完全在内存中时, Doc Values 提供对映射的快速处理能力,另一方面当映射非常大时,可以通过溢出到磁盘提供足够的扩展能力
建立索引:
- PUT order
- {
- "mappings": {
- "order": { --> 父文档
- "properties": { --> 父文档字段属性
- "id": {
- "type": "integer"
- },
- "order_no": {
- "type": "long"
- },
- "amount": {
- "type": "double"
- }
- }
- },
- "order_detail": { --> 子文档
- "_parent": { --> 指定子文档的父亲
- "type": "order"
- },
- "properties": {
- "id": { "type": "integer" },
- "order_id": { "type": "integer" },
- "commodity": { "type": "text" },
- "price": { "type": "double" }
- }
- }
- }
- }
创建父文档:
- PUT /order/order/1 --> PUT /索引/文档/唯一标识(不写默认生成)
- {
- "id": "1",
- "order_no": "123456",
- "amount": "20"
- }
- 创建子文档:
-
- PUT /order/order_detail/1?parent=1 --> 在创建子文档的时候需要使用parent=?指定父文档是谁!!!该处指定父文档为标识为1的order
- {
- "id": "1",
- "order_id": "1",
- "commodity": "小米",
- "price": "15"
- }
-
- PUT order/order_detail/2?parent=1
- {
- "id": "2",
- "order_id": "1",
- "commodity": "番茄",
- "price": "5"
- }
- 查询父文档,并显示所有子文档:
-
- GET order/order/_search
- {
- "query": {
- "has_child": {
- "type": "order_detail",
- "query": {
- "match_all": {}
- },
- "inner_hits": {} --> 显示所有子文档
- }
- }
- }
查询结果:
- {
- "took": 2,
- "timed_out": false,
- "_shards": {
- "total": 5,
- "successful": 5,
- "skipped": 0,
- "failed": 0
- },
- "hits": {
- "total": 1,
- "max_score": 1,
- "hits": [
- {
- "_index": "order",
- "_type": "order",
- "_id": "1",
- "_score": 1,
- "_source": {
- "id": "1",
- "order_no": "123456",
- "amount": "20"
- },
- "inner_hits": {
- "order_detail": {
- "hits": {
- "total": 2,
- "max_score": 1,
- "hits": [
- {
- "_type": "order_detail",
- "_id": "1",
- "_score": 1,
- "_routing": "1",
- "_parent": "1",
- "_source": {
- "id": "1",
- "order_id": "1",
- "commodity": "小米",
- "price": "15"
- }
- },
- {
- "_type": "order_detail",
- "_id": "2",
- "_score": 1,
- "_routing": "1",
- "_parent": "1",
- "_source": {
- "id": "2",
- "order_id": "1",
- "commodity": "番茄",
- "price": "5"
- }
- }
- ]
- }
- }
- }
- }
- ]
- }
- }
复杂父子文档聚合查询:
- GET order/order/_search
- {
- "size": 0,
- "aggs": {
- "sum_amount": { -->指定聚合文档order,求amount字段sum值,并取名为sum_amount
- "sum": {
- "field": "amount"
- }
- },
- "detail": {
- "children": { --> 指定子文档为order_detail
- "type": "order_detail"
- },
- "aggs": { --> 子文档聚合操作,求子文档price字段sum值,并取名为sum_price
- "sum_price": {
- "sum": {
- "field": "price"
- }
- }
- }
- }
- }
- }
查询结果:
- {
- "took": 0,
- "timed_out": false,
- "_shards": {
- "total": 5,
- "successful": 5,
- "skipped": 0,
- "failed": 0
- },
- "hits": {
- "total": 1, --> order文档一共一条记录
- "max_score": 0,
- "hits": []
- },
- "aggregations": {
- "sum_amount": { --> 父文档sum(amount)结果
- "value": 20
- },
- "detail": { --> 子文档
- "doc_count": 2, --> 子文档一共两条记录
- "sum_price": { --> 子文档sum(price)结果
- "value": 20
- }
- }
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。