亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

Elastic search中使用nested類型的內嵌對象

標簽:
深度學習

在大数据的应用环境中,往往使用反范式设计来提高读写性能。
假设我们有个类似简书的系统,系统里有文章,用户也可以对文章进行赞赏。在关系型数据库中,如果按照数据库范式设计,需要两张表:一张文章表和一张赞赏历史记录表,赞赏历史记录表包括了赞赏者姓名和赞赏金额。
在Elastic search中,由于都是json格式存储,则可以在一个index存储系统中的文章及其赞赏记录,这种情况下需要在elastic search中使用nested类型的内嵌对象。因为如果使用数组或者object对象的话,赞赏者姓名和赞赏金额是相互独立的进行存储,不能被正确的关联。

建立index

PUT articles
{  "mappings": {    "doc": {      "properties": {        "payment": {          "type": "nested",          "properties": {            "amount": {              "type": "integer"
            },            "name": {              "type": "keyword"
            }
          }
        }
      }
    }
  }
}

这样articles就有了payment这个nested类型的字段,payment里面的对象有amount和name,表示金额和姓名。

产生数据

产生如下数据,表示jack给文章1赞赏了29元,ross给文章1赞赏30元,ross给文章2赞赏31元。

POST articles/doc/1
{  "payment": [
    {      "name": "jack",      "amount": 29
    },
    {      "name": "ross",      "amount": 30
    }
  ]
}

POST articles/doc/2
{  "payment": [
    {      "name": "ross",      "amount": 31
    }
  ]
}

根据内嵌对象进行查询

现在想查询ross赞赏过的文章,需要使用nested query

GET articles/_search
{  "query": {    "nested": {      "path": "payment",      "query": {        "term": {          "payment.name": {            "value": "ross"
          }
        }
      }
    }
  }
}

path表示了nested字段的名称,需要注意的是,查询语句中要指定查询字段的全名,所以赞赏者姓名要用"payment.name"
如果在多个index上进行nested查询,没有nested字段的index会报错,这时可以将ignore_unmapped设置为true

nested对象聚合

如果想查看赞赏的平均金额,需要用nested aggregation

GET articles/_search
{  "size": 0, 
  "aggs": {    "nested": {      "nested": {        "path": "payment"
      },      "aggs": {        "amount_avg": {          "avg": {            "field": "payment.amount"
          }
        }
      }
    }
  }
}

同样注意要用path指定字段名称。返回的数据中,比普通的聚合查询多了一层嵌套
返回结果为

{  "took": 1,  "timed_out": false,  "_shards": {    "total": 5,    "successful": 5,    "skipped": 0,    "failed": 0
  },  "hits": {    "total": 2,    "max_score": 0,    "hits": []
  },  "aggregations": {    "nested": {      "doc_count": 3,      "amount_avg": {        "value": 30
      }
    }
  }
}

nested对象聚合和过滤

如果想看ross赞赏过的总金额,一开始写出query如下

GET articles/_search
{  "size": 0, 
  "query": {    "nested": {      "path": "payment",      "query": {        "term": {          "payment.name": {            "value": "ross"
          }
        }
      }
    }
  },  "aggs": {    "nested": {      "nested": {        "path": "payment"
      },      "aggs": {        "sum": {          "sum": {            "field": "payment.amount"
          }
        }
      }
    }
  }
}

此时结果并不是正确的,因为上面的query过滤的是ross赞赏过的文章,下面的聚合操作sum的是文章里所有的赞赏,包括了jack的赞赏。
所以需要在sum聚合操作之前,需要用Filter Aggregation筛选ross的赞赏。

GET articles/_search
{  "size": 0,  "query": {    "nested": {      "path": "payment",      "query": {        "term": {          "payment.name": {            "value": "ross"
          }
        }
      }
    }
  },  "aggs": {    "payment": {      "nested": {        "path": "payment"
      },      "aggs": {        "payer": {          "filter": {            "term": {              "payment.name": {                "value": "ross"
              }
            }
          },          "aggs": {            "sum": {              "sum": {                "field": "payment.amount"
              }
            }
          }
        }
      }
    }
  }
}

最外层的query筛选出ross赞赏过的文章。
第一层的aggs表示进行内嵌聚合。
第二层的aggs用Filter Aggregation筛选出表示ross赞赏行为的nested对象。
第三层的aggs进行聚合。



作者:大神带我来搬砖
链接:https://www.jianshu.com/p/d685b7b6c9d1

點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消