通过嵌套字段进行分组的Mongoose聚合问题

时间:2014-07-30 21:27:58

标签: mongodb mongoose

我有一个架构存储用户参加活动:

event: 
  _id: ObjectId,
  ...
  attendances: [{
    user: {
      type: ObjectId,
      ref: 'User'
    },
    answer: {
      type: String,
      enum: ['yes', 'no', 'maybe']
    }
  }]
}

示例数据:

_id: '533483aecb41af00009a94c3',
attendances: [{
  user: '531770ea14d1f0d0ec42ae57',
  answer: 'yes',
}, {
  user: '53177a2114d1f0d0ec42ae63',
  answer: 'maybe',
}],

当我查询用户的所有出席情况时,我想以下列格式返回此数据:

var attendances = {
  yes: ['533497dfcb41af00009a94d8'], // These are the event IDs
  no: [],
  maybe: ['533497dfcb41af00009a94d6', '533497dfcb41af00009a94d2']
}

我不确定aggegation管道会以这种格式返回它吗?所以我想我可以回复并轻松修改它:

var attendances = [
  answer: 'yes',
  ids: ['533497dfcb41af00009a94d8'],
},{
  answer: 'no',
  ids: ['533497dfcb41af00009a94d8']
}, {
  answer: 'maybe',
  ids:  ['533497dfcb41af00009a94d6', '533497dfcb41af00009a94d2']
}];

然而,我的尝试并不成功。它没有按答案分组:

this.aggregate({
  $match: {
    'attendances.user': someUserId
}
}, {
  $project: {
    answer: '$attendances.answer' 
  }
}, {
  $group: {
    _id: '$answer',
    ids: {
      $addToSet: "$_id"
    }
  }
}, function(e, docs) {

});

我能否以第一种所需格式返回我需要的数据?如果不能,我如何更正上述代码以达到预期效果?

就此而言 - 也许map-reduce过程更适合?

1 个答案:

答案 0 :(得分:1)

以下查询将帮助您接近所需的答案。虽然它并不完全符合您期望的格式,但您可以为每个答案选项和一系列事件ID获取单独的文档。

db.collection.aggregate([
    // Unwind the 'attendances' array
    {"$unwind" : "$attendances"}, 
    // Match for user
    {"$match" : {"attendances.user" : "53177a2114d1f0d0ec42ae63"}}, 
    // Group by answer and push the event id's to an array
    {"$group" : {_id : "$attendances.answer", eventids : {$push : "$_id"}}}
])

这会产生以下输出:

{
        "result" : [
                {
                        "_id" : "yes",
                        "eventids" : [
                                ObjectId("53d968a8c4840ac54443a9d6")
                        ]
                },
                {
                        "_id" : "maybe",
                        "eventids" : [
                                ObjectId("53d968a8c4840ac54443a9d7"),
                                ObjectId("53d968a8c4840ac54443a9d8")
                        ]
                }
        ],
        "ok" : 1
}