首页 > 解决方案 > 使用聚合框架转换具有两个嵌套文档的文档

问题描述

我需要使用聚合框架转换此文​​档

{
  title: 'Sample title',
  options: [
    { text: "yes", id: 0 },
    { text: "no", id: 1 }
  ],
  votes: [
    { option_id: 1, user_id: 1 },
    { option_id: 1, user_id: 2 },
    { option_id: 1, user_id: 3 }
  ]
}

进入这个对象

{ 
 title: 'Sample title',
 result: [{ _id: 1, text: 'no', votes: 3}, { _id: 0, text: 'yes', votes: 0 }]
}

我试过的:

[
            { $match: { _id: poll_id } },
            { $unwind: '$votes' },
            {
                $replaceRoot: {
                    newRoot: { $mergeObjects: ['$votes', '$$ROOT'] }
                }
            },
            {
                $group: {
                    _id: '$option_id',
                    title: { $first: '$title' },
                    votes: { $sum: 1 }
                }
            }
        ]

这产生了这个结果:

[{ _id: 1, title: 'Sample Title', votes: 3}]

如果该选项没有投票,则将其排除在最终结果之外。我也不知道如何包含选项的文本。我已经阅读了 mongodb 参考,但我找不到任何东西。

标签: node.jsmongodbaggregation-framework

解决方案


您可以使用以下利用$map$filter的管道:

db.collection.aggregate([
    {
        "$addFields": {
            "result": {
                "$map": {
                    "input": "$options",
                    "as": "option",
                    "in": {
                        "_id": "$$option.id",
                        "text": "$$option.text",
                        "votes": {
                            "$size": {
                                "$filter": {
                                    "input": "$votes",
                                    "as": "vote",
                                    "cond": {
                                        "$eq": [
                                            "$$vote.option_id",
                                            "$$option.id"
                                        ]
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    {
        "$project": {
             title: "$title",
             "result": {
                $filter: {
                   input: "$result",
                   as: "option",
                   cond: {
                      $gt: ["$$option.votes", 0]
                   }
                }
           }
       }
    }
])

推荐阅读