博客专栏 产品中心 技能中心

MongoDB 聚合嵌入的数组(扁平化数据+管道)

· 原创专栏 · 阅读 5

MongoDB学习教程:https://piaosanlang.gitbooks.io/mongodb/

先看下要操作的主要数据结构:

{
‍    "_id" : "000015e0-3e9c-40b3-bd0d-6e7949f455c0",      "evaluation_type" : 2,      "reply_count" : 5,      "type" : 3,      "content" : "怎么编制余额调节表",      "tips" : [          {              "_id" : 1000,              "tip_name" : "会计基础"          }      ],      "teach_id" : 10298153  â€
}

看这个文档数据,现在要以 tips 数组下的 _id 做数据的分组查询。在查询条件中使用 "tips.0._id":1000 过滤数据是可以生效的,但用在 aggregate 聚合查询中的 group 分组条件中是不行的,必须得先使用 $unwind ( 文档地址:https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/ )把 tips 这个数组对象变成扁平的结构(把数组中的每个对象拆分出来与当前文档重新组合,达到消数组的效果)

上面数据根据以下查询语句的前后变化

扁平化前:

db.getCollection(‘topics’).
       find({“teach_id”:10010943})


扁平化后:

db.getCollection('topics').
       aggregate({'$match':{"teach_id":10010943}},{'$unwind':'$tips'})


关注扁平化前后 tips 由数组变成了对象

通过 {'$unwind' : '$tips'} å¯¹æ–‡æ¡£æ‰å¹³åŒ–结构之后,然后再用 pipeline (管道)的方式做聚合就好了,可以直接根据 tips._id è¿›è¡Œåˆ†ç»„了

查询语句:

db.getCollection('topics').
   aggregate(
       {'$match':{"teach_id":10010943}},{'$unwind':'$tips'},        {'$group':{'_id':{"tipId":'$tips._id',"tipName":'$tips.tip_name',"evaluationType":'$evaluation_type'},
           "count":{'$sum': 1}}},        {'$project':{"tipId":'$_id.tipId',"tipName":'$_id.tipName',"evaluationType":'$_id.evaluationType',
           "count":'$count'}}
    )


完美滴根据 tipId,tipName,evaluationType 分好组了

关注公众号,分享干货,讨论技术