Mongo按计算条件排序

bea*_*ght 6 mongodb mongodb-query aggregation-framework

我有一个Mongo的消息集合,如下所示:

{
  'recipients': [],
  'unRead': [],
  'content': 'Text'
}
Run Code Online (Sandbox Code Playgroud)

收件人是一组用户ID,unRead是尚未打开邮件的所有用户的数组.这是按预期工作,但我需要查询所有消息的列表,以便它返回前20个结果,首先优先考虑未读的结果,如下所示:

db.messages.find({recipients: {$elemMatch: userID} })
  .sort({unRead: {$elemMatch: userID}})
  .limit(20)
Run Code Online (Sandbox Code Playgroud)

但这不起作用.根据结果​​是否符合某个标准,对结果进行优先排序的最佳方法是什么?

Bla*_*ven 6

如果您想按某些标准"加权"结果或在"排序"中具有任何类型的"计算值",则需要使用该.aggregate()方法.这允许在$sort操作中使用"投影"值,对于该操作,只能使用文档中的当前字段:

db.messages.aggregate([
    { "$match": { "messages": userId } },
    { "$project": {
        "recipients": 1,
        "unread": 1,
        "content": 1,
        "readYet": {
            "$setIsSubset": [ [userId], "$unread" ] }
        }
    }},
    { "$sort": { "readYet": -1 } },
    { "$limit": 20 }
])
Run Code Online (Sandbox Code Playgroud)

这里$setIsSubset操作符允许将"未读"数组与转换后的数组进行比较,[userId]以查看是否存在任何匹配.结果将是trueuserId存在的位置或false不存在的位置.

然后可以将其传递给$sort,其优先于匹配(降序排序true在顶部)对结果进行排序,最后$limit只返回指定量的结果.

因此,为了使用计算的术语进行"排序",需要将值"投影"到文档中,以便对其进行排序.聚合框架就是你如何做到这一点的.

另请注意,$elemMatch只需匹配数组中的单个值,您只需要直接指定值即可.它的目的是在单个数组元素上需要满足"多个"条件,这当然不适用于此.