我正在尝试从节点上的MongoDB获取文档.假设文档具有以下结构: { "_id": ObjectId, "title" : String, "tags" : ArrayString } 我想按相关性对它们进行排序 – 所以当我正在寻找具有“蓝色”或“黄色
{ "_id": ObjectId, "title" : String, "tags" : Array<String> }
我想按相关性对它们进行排序 – 所以当我正在寻找具有“蓝色”或“黄色”标签的文档时,我希望首先获得具有两个标签的文档.到目前为止,我通过谷歌,试验和错误管理:
var tags = [ "yellow", "blue" ]; db.collection('files').aggregate([ { $project : { tags: 1 } }, { $unwind : "$tags" }, { $match : { "tags": { "$in": tags } } }, { $group : { _id: "$_id", relevance: { $sum:1 } } }, { $sort : { relevance : -1 } }, ], function(err, success) { console.log(success); });
它运行得很好,我得到了有序ID的集合:
[{"_id":"5371355045002fc820a09566","relevance":2},{"_id":"53712fc6c8fcd124216de6cd","relevance":2},{"_id":"5371302ebd4725dc1b908316","relevance":1}]
现在我将进行另一个查询并询问带有这些ID的文档 – 但这是我的问题:可以在一个查询中完成吗?
是的,当您实际上在_id上进行分组时,您可以始终如此,那么该值基本上等同于整个文档.因此,只需将整个文档存储在_id字段下即可.根据您的MongoDB版本,您有几种方法,在MongoDB 2.6之前的版本中,您必须在初始的$project
阶段(可能选择在$match
之后,这通常是一个好主意)中指定整个文档结构.在实际操作文档之前的管道:
var tags = ["yellow","blue"]; db.collection.aggregate([ { "$project" : { "_id": { "_id": "$_id", "title": "$title", "tags": "$tags" }, "tags": 1 }}, { "$unwind": "$tags" }, { "$match": { "tags": { "$in": tags } } }, { "$group": { "_id": "$_id", "relevance": { "$sum":1 } } }, { "$sort": { "relevance" : -1 } }, { "$project": { _id: "$_id._id", "title": "$_id.title", "tags": "$_id.tags" }} ])
当然,在管道的末尾,您可以从_id字段中提取信息,以便恢复原始结构.这是可选的,但你通常想要那个.
对于MongoDB 2.6及更高版本,管道阶段可以使用一个变量,该变量在管道的那个阶段($$ROOT
)保存文档的结构,您可以将其作为上述表单的一种快捷方式访问,如下所示:
var tags = ["yellow","blue"]; db.collection.aggregate([ { "$project" : { "_id": "$$ROOT", "tags": 1 }}, { "$unwind": "$tags" }, { "$match": { "tags": { "$in": tags } } }, { "$group": { "_id": "$_id", "relevance": { "$sum":1 } } }, { "$sort": { "relevance" : -1 } }, { "$project": { "_id": "$_id._id", "title": "$_id.title", "tags": "$_id.tags" }} ])
请记住,为了还原文档,您仍需要指定所有必需的字段.
我会注意到,在这种情况下,如果您使用匹配条件“过滤”文档,并且如前所述,您实际上应该在管道的“头部”使用$match
语句进行过滤.这是聚合框架可以选择索引以优化查询的唯一位置,它还减少了不符合条件的文档数量(假设并非所有文档都标记为“黄色”或“蓝色”)通过剩余的管道阶段:
db.collection.aggregate([ { "$match": { "tags": { "$in": tags } } }, { "$project" : { "_id": { "_id": "$_id", "title": "$title", "tags": "$tags" }, "tags": 1 }}, { "$unwind": "$tags" }, { "$match": { "tags": { "$in": tags } } }, { "$group": { "_id": "$_id", "relevance": { "$sum":1 } } }, { "$sort": { "relevance" : -1 } }, { "$project": { _id: "$_id._id", "title": "$_id.title", "tags": "$_id.tags" }} ])
无论如何,这通常比尝试进行另一个查询更有效,因为当然不会以您完成的方式维护您的排序顺序.