Mongo在计算条件上排序

25 浏览
0 Comments

Mongo在计算条件上排序

我有一个消息的Mongo集合,看起来像这样:

{
  'recipients': [],
  'unRead': [],
  'content': 'Text'
}

Recipients是一个用户ID的数组,而unRead是一个尚未打开消息的所有用户的数组。这正如预期的那样工作,但我需要查询所有消息的列表,以便返回前20个结果,优先考虑未读的消息,类似于:

db.messages.find({recipients: {$elemMatch: userID} })
  .sort({unRead: {$elemMatch: userID}})
  .limit(20)

但这并不起作用。基于特定条件如何优先处理结果的最佳方法是什么?

0
0 Comments

在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" ]

0