首页 > 解决方案 > 从嵌套对象投影平面值

问题描述

我正在猫鼬中编写一个小型聚合来过滤来自 db 的值并按它们出现的频率顺序返回它们。例如:假设多个文档将合作伙伴数组作为一个字段,它是一个对象数组,每个对象都有两个值“partner_id”和“passed_tests”。我想从所有文档中返回所有唯一合作伙伴,这些文档根据它们在集合中的频率以降序排列。

这是一个示例文档:

{
    "location": "eindhoven",
    "partners": [
        {
            "partner_id": 3,
            "passed_tests": true
        },
        {
            "partner_id": 2,
            "passed_tests": false
        }
    ],
    "_id": "3136323031333066306d4438",
    "uid": "d95f2e446c052514c097e6c925408774",
    "__v": 0,
    "is_approved": true
}

我的代码如下:

function returnAll(callback) {
    TestService.aggregate([
        {
            $match: { "is_approved": true }
        },
        {
            $unwind: "$partners"
        }, {
            $group: {
                "_id": {
                    partner: { $objectToArray: "$partners" },
                    partner_id: { $arrayElemAt: ["$partner", 0] }
                },
                "count": { "$sum": 1 }
            }
        },
        {
            $sort: { "count": -1 }
        },
        {
            $project: {
                "partner_values": {
                    $map: {
                        input: "$_id.partner",
                        as: "el",
                        in: {
                            $cond: {
                                if: {
                                    $or: [{ $eq: ["$$el.v", true] },
                                    { $eq: ["$$el.v", false] }]
                                }, then: {
                                    "passed_tests": "$$el.v"
                                }, else: {
                                    "id": "$$el.v"
                                }
                            }
                        }
                    }
                },
                "count": "$count,
                "_id": 0
            }
        },
    ], function (error, data) {
        if (error) {
            logger.error(error);
            callback(null);
        } else {
            callback(data);
        }
    });
}

它将这个 JSON 返回到我的节点应用程序:

"data": [
        {
            "partner_values": [
                {
                    "id": 2
                },
                {
                    "passed_tests": false
                }
            ],
            "count": 3
        },
        {
            "partner_values": [
                {
                    "id": 6
                },
                {
                    "passed_tests": true
                }
            ],
            "count": 1
        },
        {
            "partner_values": [
                {
                    "id": 3
                },
                {
                    "passed_tests": true
                }
            ],
            "count": 1
        },
        {
            "partner_values": [
                {
                    "id": 1
                },
                {
                    "passed_tests": true
                }
            ],
            "count": 1
        }
    ]

如果我不在聚合中使用投影管道,我会得到:

"data": [
        {
            "_id": {
                "partner": [
                    {
                        "k": "partner_id",
                        "v": 2
                    },
                    {
                        "k": "passed_tests",
                        "v": false
                    }
                ],
                "partner_id": null
            },
            "count": 3
        },
        {
            "_id": {
                "partner": [
                    {
                        "k": "partner_id",
                        "v": 6
                    },
                    {
                        "k": "passed_tests",
                        "v": true
                    }
                ],
                "partner_id": null
            },
            "count": 1
        },
        {
            "_id": {
                "partner": [
                    {
                        "k": "partner_id",
                        "v": 3
                    },
                    {
                        "k": "passed_tests",
                        "v": true
                    }
                ],
                "partner_id": null
            },
            "count": 1
        },
        {
            "_id": {
                "partner": [
                    {
                        "k": "partner_id",
                        "v": 1
                    },
                    {
                        "k": "passed_tests",
                        "v": true
                    }
                ],
                "partner_id": null
            },
            "count": 1
        }
    ]

这是很容易理解的,因为我正在引入“_id”和其他额外的字段来查看数组并找到值。但是,我想要的输出是:

"data": {
            "partners": [{
                "id": 2,
                "passed_tests": false,
                "count": 3
            }, {
                "id": 6,
                "passed_tests": false,
                "count": 1
            }, {
                "id": 3,
                "passed_tests": false,
                "count": 1
            }, {
                "id": 1,
                "passed_tests": false,
                "count": 1
            }]
        }

请问我能得到一些帮助吗?谢谢。

标签: node.jsmongodbmongooseaggregation-framework

解决方案


您可以使用以下聚合查询。

TestService.aggregate([
  {"$match":{"is_approved":true}},
  {"$unwind":"$partners"},
  {"$group":{
    "_id":{"partner_id":"$partners.partner_id","passed_tests":"$partners.passed_tests"},
    "count":{"$sum":1}
  }},
  {"$sort":{"count":-1}},
  {"$group":{
    "_id":null,
    "partners":{"$push":{"id":"$_id.partner_id","passed_tests":"$_id.passed_tests","count":"$count"}}
  }},
  {"$project":{"partners":1}}
])

推荐阅读