MongoDB聚合,如何在组管道中添加数据的每个元素

时间:2017-11-16 15:01:33

标签: arrays mongodb aggregation-framework aggregate each

我有包含标签字段的文档。它是一个简单的数组,里面有标记名,里面没有对象也没有_id。 只需像["Protocol", "Access", "Leverage", "Capability"]这样的普通标签。

在我的小组管道中,我尝试了类似'selectedTags': { $addToSet: '$tags' }的内容,但后来最终得到了一个包含标签数组的数组。我对$push也一样。

我尝试使用$each$pushAll,但不支持它们作为分组操作符,因为我的shell告诉我。

有人可以帮我解决这个问题吗?

谢谢

编辑:

示例文档:

{
    "_id" : "HWEdDGsq86x4ikDSQ",
    "teamId" : "AdLizGnPuqbWNsFHe",
    "ownerId" : "Qb5EigWjqn2t3bfxD",
    "type" : "meeting",
    "topic" : "Grass-roots hybrid knowledge user",
    "fullname" : "Guidouil",
    "startDate" : ISODate("2017-07-30T09:00:05.513Z"),
    "shareResults" : true,
    "open" : true,
    "language" : "fr",
    "tags" : [
        "Protocol",
        "Challenge",
        "Artificial Intelligence",
        "Capability"
    ],
    "isDemo" : true,
    "createdAt" : ISODate("2017-11-15T19:24:05.513Z"),
    "participantsCount" : 10,
    "ratersCount" : 10,
    "averageRating" : 3.4,
    "hasAnswers" : true,
    "updatedAt" : ISODate("2017-11-15T19:24:05.562Z")
}
{
    "_id" : "rXvkFndpXwJ6KAvNo",
    "teamId" : "AdLizGnPuqbWNsFHe",
    "ownerId" : "Qb5EigWjqn2t3bfxD",
    "type" : "meeting",
    "topic" : "Profit-focused modular system engine",
    "fullname" : "Guidouil",
    "startDate" : ISODate("2017-07-24T12:00:05.564Z"),
    "shareResults" : true,
    "open" : true,
    "language" : "fr",
    "tags" : [
        "Initiative",
        "Artificial Intelligence",
        "Protocol",
        "Utilisation"
    ],
    "isDemo" : true,
    "createdAt" : ISODate("2017-11-15T19:24:05.564Z"),
    "participantsCount" : 33,
    "ratersCount" : 33,
    "averageRating" : 2.9393939393939394,
    "hasAnswers" : true,
    "updatedAt" : ISODate("2017-11-15T19:24:05.753Z")
}

聚合:

db.surveys.aggregate(
  { $match: query },
  {
    $group: {
      '_id': {
        'year': { $year: '$startDate' },
        'day': { $dayOfYear: '$startDate' },
      },
      'participants': { $sum: '$ratersCount' },
      'rating': { $avg: '$averageRating' },
      'surveys': { $push: '$_id' },
      'selectedTags': { $addToSet: '$tags' },
      'peoples': { $addToSet: '$fullname' },
    }
  },
  { $sort: { _id: 1 } }
);

然后我尝试将selectedTags更改为{ $push: { $each: '$tags' } }{ $pushAll: '$tags' },但这不会执行:(

编辑2:

在javascript中,我这样做:

return Surveys.aggregate(
  { $match: query },
  { $group: {
    _id: dateGroup,
    participants: { $sum: '$ratersCount' },
    rating: { $avg: '$averageRating' },
    surveys: { $push: '$_id' },
    selectedTags: { $push: '$tags' },
    peoples: { $addToSet: '$fullname' },
  } },
  { $project: {
    _id: null,
    selectedTags: {
      $reduce: {
        input: "$selectedTags",
        initialValue: [],
        in: { $setUnion: ["$$value", "$$this"] }
      }
    },
  } }
);

2 个答案:

答案 0 :(得分:6)

要模仿聚合管道中$addToSet update operator with $each modifier的功能,您可以在分组阶段使用$push和在投影阶段使用$reduce + $setUnion。 E.g:

db.collection.aggregate([
    {$group:{
       _id: null,
       selectedTags: { $push: '$tags' }      
    }},
    {$project: {
        selectedTags: { $reduce: {
            input: "$selectedTags",
            initialValue: [],
            in: {$setUnion : ["$$value", "$$this"]}
        }}
    }}
])

结果是单个文档,其中包含selectedTags数组中所有文档的不同标记列表。

答案 1 :(得分:2)

您也可以使用$unwind来获得结果:

db.collection.aggregate([
  {$unwind: "$tags"},
  {$group:{
     _id: null,
     selectedTags: { $addToSet: '$tags' }      
  }}
])