Mongo在计算条件上排序
Mongo在计算条件上排序
我有一个消息的Mongo集合,看起来像这样:
{ 'recipients': [], 'unRead': [], 'content': 'Text' }
Recipients是一个用户ID的数组,而unRead是一个尚未打开消息的所有用户的数组。这正如预期的那样工作,但我需要查询所有消息的列表,以便返回前20个结果,优先考虑未读的消息,类似于:
db.messages.find({recipients: {$elemMatch: userID} }) .sort({unRead: {$elemMatch: userID}}) .limit(20)
但这并不起作用。基于特定条件如何优先处理结果的最佳方法是什么?
在MongoDB中,如果想要根据某些标准对结果进行"加权"或者在"排序"中使用任何类型的"计算值",则需要使用.aggregate()
方法。这允许在$sort
操作中使用"投影"值,而在该操作中,只能使用文档中存在的字段:
db.messages.aggregate([ { "$match": { "messages": userId } }, { "$project": { "recipients": 1, "unread": 1, "content": 1, "readYet": { "$setIsSubset": [ [userId], "$unread" ] } } }}, { "$sort": { "readYet": -1 } }, { "$limit": 20 } ])
这里的$setIsSubset
操作符允许将"unread"数组与转换后的[userId]
数组进行比较,以查看是否存在任何匹配项。结果要么是true
(userId存在),要么是false
(userId不存在)。
然后,可以将这个结果传递给$sort
,它根据匹配项的优先级对结果进行排序(降序排序时,true
排在前面),最后,$limit
只返回指定数量的结果。
因此,为了在"排序"中使用计算值,需要将该值"投影"到文档中以便进行排序。聚合框架是实现这一点的方法。
还要注意,$elemMatch
不是必需的,只需直接指定数组中的单个值即可匹配。它的目的是在单个数组元素上需要满足"多个"条件时使用,而在这里显然不适用。
这个方法运行得非常完美。谢谢!我只想提一点,直到我将$setIsSubSet
改为$setIsSubset
,Mongo才抛出了一个错误。
典型的我。文档链接是正确的,但我这个驼峰式大脑总是认为它是两个单词,并且一直这样输入。
最好使用$in
而不是$setIsSubset
。所以:"$in": [ userId, "$unread" ]
。