我有一个Mongo的邮件集合,如下所示:
{
'recipients': [],
'unRead': [],
'content': 'Text'
}
收件人是一组用户ID,而unRead是一个尚未打开邮件的所有用户的数组。这是按预期工作的,但我需要查询所有消息的列表,以便它返回前20个结果,首先优先考虑未读的结果,如:
db.messages.find({recipients: {$elemMatch: userID} })
.sort({unRead: {$elemMatch: userID}})
.limit(20)
但这不起作用。根据结果是否符合某个标准,对结果进行优先排序的最佳方法是什么?
答案 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
。
然后可以将其传递给$sort
,true
会优先对匹配项进行排序(降序排序为$elemMatch
,最后$limit
只返回结果指定金额。
因此,为了使用计算的术语进行“排序”,需要将值“投影”到文档中,以便对其进行排序。聚合框架就是你这样做的。
另请注意,{{1}}不仅仅是为了匹配数组中的单个值,您只需要直接指定值。它的目的是在单个数组元素上需要满足“多个”条件,这当然不适用于此。