node.js - 从嵌套对象投影平面值
问题描述
我正在猫鼬中编写一个小型聚合来过滤来自 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
}]
}
请问我能得到一些帮助吗?谢谢。
解决方案
您可以使用以下聚合查询。
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}}
])
推荐阅读
- matlab - 如何以编程方式在 Simulink 模型中设置 To File 模块参数?
- kubernetes - 外部服务的 Kubernetes 入口规则
- reactjs - 使用反应表中的选择下拉列表过滤数据
- git - 在 CI 中的克隆操作期间如何对 github 子模块进行身份验证?
- c# - 反序列化 XML 文件属性
- python - 有人可以帮我在 Python 中使用 pip 吗?
- webrtc - 连接问题 webRTC 应用程序。只能在本地工作,不能在移动设备上工作
- c# - 并行运行多个任务会导致 System.AggregateException
- javascript - 使用 Telegraf/Node.js 等待消息响应
- java - 如何配置 ResourceHttpRequestHandler 支持的方法?