我在这个给定的聚合上遇到了性能问题:
db.users.aggregate([
{
// reduce to users that have first or second level users in their friends list
"$match:": {"friendOf": {"$in": [ObjectId("59b1b8025c69f2ae693f36d7"), ObjectId("59b1b8025c69f2ae693f36d8"), ObjectId("59b309835c69f24829057eb5"), ObjectId("59b458aa5c69f272513907e5")}}
},
{
"$addFields": {
"ranking": {
"$sum": [
{
"$cond": {
"if": { // first level friends
"$setIsSubset": ["$friendOf", [ObjectId("59b1b8025c69f2ae693f36d7"), ObjectId("59b1b8025c69f2ae693f36d8")]]
},
"then": 2, // weight: 2
"else": 0
}
},
{
"$cond": {
"if": { // second level friends
"$setIsSubset": ["$friendOf": [ObjectId("59b309835c69f24829057eb5"), ObjectId("59b458aa5c69f272513907e5")]]
},
"then": 1, // weight: 1
"else": 0
}
}
]
}
}
},
{
"$sort": {"ranking": 1}
},
{
"$limit": 20
}
]);
使用用户集合,其中'friendOf'属性获取对应的ObjectId()列表,如果用户有其他用户为朋友。
查询的目标是按用户与第一个用户列表的接近程度对用户进行排序。
我遇到的问题是我使用“排名”键作为排序字段。
由于它是一个依赖于查询的投影,我无法预先计算并存储此字段以使Mongo索引受益。
由于查询的目的是排名,我不能在$ sort之前“限制”范围。
所以,我正在寻找一种更好的方法来解决我的问题。
注意:我使用的是MongoDB 3.4.10版本
此致
答案 0 :(得分:0)
实际上你只有2级朋友吗? 1点和2点?你会想看到21-40的结果吗?如果没有,那么您可以简单地对MongoDB进行两次查询,并在_id
和$sum:1
上使用$ group来获取朋友总数,在AF内执行$ sort和$ limit 20步骤然后合并你的应用程序中的2和度假,以应用2分评分。