Mongo按计算条件排序

时间:2015-10-05 21:43:21

标签: mongodb mongodb-query aggregation-framework

我有一个Mongo的邮件集合,如下所示:

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

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

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

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

1 个答案:

答案 0 :(得分:5)

如果您想按某些条件“加权”结果,或者在“排序”中有任何“计算值”,则需要使用.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运算符允许将“未读”数组与转换后的[userId]数组进行比较,以查看是否存在任何匹配项。结果将是{I}存在的true或不存在的false

然后可以将其传递给$sorttrue会优先对匹配项进行排序(降序排序为$elemMatch,最后$limit只返回结果指定金额。

因此,为了使用计算的术语进行“排序”,需要将值“投影”到文档中,以便对其进行排序。聚合框架就是你这样做的。

另请注意,{{1}}不仅仅是为了匹配数组中的单个值,您只需要直接指定值。它的目的是在单个数组元素上需要满足“多个”条件,这当然不适用于此。