我有post
这样的文件:
post = {
"_id": "uid1",
"userID": "user1",
"likeNum": 30,
}
我当前的管道如下所示,其中包含user_ids
要避免的用户 ID 数组以及seen_ids
要避免的帖子 ID 数组:
fake_pipeline = [
{'$match': {'userID': {'$nin': user_ids}, '_id': {"$nin": seen_ids}}},
{'$group': {'_id': '$userID', 'posts': {'$push': '$likeNum'}}},
{'$project': {'posts': {'$slice': [{'$sortArray': {'input': '$posts', 'sortBy': {'likeNum': -1}}}, 2]}}},
{'$limit': 10}
]
我希望聚合返回一个post
按排序的 10 个列表,但每个likeNum
descending
最多 2 个。post
userID
例子 :
post_list_in_db = [
{"_id": "uid1", "userID": "user1", "likeNum": 29},
{"_id": "uid2", "userID": "user1", "likeNum": 2},
{"_id": "uid3", "userID": "user1", "likeNum": 13},
{"_id": "uid4", "userID": "user2", "likeNum": 21},
{"_id": "uid5", "userID": "user2", "likeNum": 19},
{"_id": "uid6", "userID": "user3", "likeNum": 1},
{"_id": "uid7", "userID": "user3", "likeNum": 8},
{"_id": "uid8", "userID": "user3", "likeNum": 14},
{"_id": "uid9", "userID": "user3", "likeNum": 4},
{"_id": "uid10", "userID": "user4", "likeNum": 20},
{"_id": "uid11", "userID": "user4", "likeNum": 9},
{"_id": "uid12", "userID": "user4", "likeNum": 11},
]
预期输出为:
[
{"_id": "uid1", "userID": "user1", "likeNum": 29},
{"_id": "uid4", "userID": "user2", "likeNum": 21},
{"_id": "uid10", "userID": "user4", "likeNum": 20},
{"_id": "uid5", "userID": "user2", "likeNum": 19},
{"_id": "uid8", "userID": "user3", "likeNum": 14},
{"_id": "uid3", "userID": "user1", "likeNum": 13},
{"_id": "uid12", "userID": "user4", "likeNum": 11},
{"_id": "uid7", "userID": "user3", "likeNum": 8},
]
注意:出于性能原因,我希望使用最少的代码aggregation
,不需要像示例输出那样完美地格式化数据,除非它对性能没有影响,否则我更喜欢自己在代码中重新排序/转换对象,只要我有正确的post
列表内容(但没有特别的格式或顺序)作为聚合的输出。
您已经非常接近您的需要了。
$likeNum
在该阶段之后进行排序$match
。然后,当您
$group
使用 userID 时,您可以使用$firstN
聚合累加器仅选择每个用户的前 2 个帖子。因此,这些将是likeNum
每个 UserID 最高的 2 个(因为我们在此之前进行了排序)。"$$ROOT"
来获取实际的帖子文档而不仅仅是likeNum
。然后解开累积的
"$posts"
,将其替换为文档本身,然后再次按排序likeNum
。(蓝色部分与您的管道不同。)
Mongo Playground。(第一
$match
阶段没有变化,我只是将["user3"]
和["uid9"]
作为值放在了游乐场示例中。)关于“我更喜欢自己在代码中重新排序/转换对象” ——第一个排序不能/不应该在代码中完成,因为它是针对比赛后的所有帖子。第二个
$sort
可以在代码中完成,但它可能比让 MongoDB 排序然后只选择 10 个结果要慢。否则,您需要获取所有结果,然后自己排序和限制。如果您计划进行分页,MongoDB 必须在完成排序后完成跳过 + 限制步骤。