【发布时间】:2019-06-23 07:01:53
【问题描述】:
我有两个包含员工和项目的集合。每个项目都有一个标签数组,每个员工都有一个偏好数组,其中每个偏好都是一个具有标签和分数属性的对象(员工偏好有一个基于他们选择它们的顺序的分数)。
员工示例:
[{
"name":"employee1",
"preferences":[
{
"tag": "tag1",
"score": 3
},
{
"tag": "tag2",
"score": 2
}
]
},
{
"name":"employee2",
"preferences":[
{
"tag": "tag2",
"score": 3
},
{
"tag": "tag3",
"score": 2
}
]
}]
项目示例:
[{
"name":"project1",
"tags":["tag1", "tag2"]
},
{
"name":"project2",
"tags":["tag2", "tag3"]
}]
期望的输出:
[{
"project": "project1",
"employee": "employee1",
"score": 5
},
{
"project": "project2",
"employee": "employee1",
"score": 2
},
{
"project": "project1",
"employee": "employee2",
"score": 2
},
{
"project": "project2",
"employee": "employee2",
"score": 5
}]
我写了这个聚合管道,它给了我想要的输出(不完全相同,只是添加一个投影阶段):
db.employees.aggregate([
{
'$unwind' : '$preferences'
},
{
'$lookup' : {
'from' : 'projects',
'localField' : 'preferences.tag',
'foreignField': 'tags',
'as' : 'match'
}
},
{
'$group' :
{
'_id': {'project' : '$match.name', 'employee' : '$name' },
'score' : { '$sum' : '$preferences.score' }
}
},
{
'$unwind': '$_id.project'
},
{
'$group' :
{
'_id': {'project' : '$_id.project', 'employee' : '$_id.employee' },
'score' : { '$sum' : '$score' }
}
}
])
现在这是一个可行的解决方案,但我不确定它是否是最好的。我正在对可变数量的文档进行一些测试,每个集合从 100 到 5000,我将它与使用嵌套 for 循环的简单迭代方法进行比较,结果是迭代方法实际上更快更轻(在更短的时间内执行,使用更少的内存)。 我认为聚合会更好地增加文档数量,但似乎并非如此。你有什么改进管道的建议吗?一般有什么想法吗?提前谢谢你:)
【问题讨论】:
标签: mongodb aggregation-framework