MongoDB按相关性sorting

我正在使用试图从节点上的MongoDB获取文档。 假设文档具有以下结构:

{ "_id": ObjectId, "title" : String, "tags" : Array<String> } 

我想按照相关性对它们进行sorting – 所以当我在查找具有“蓝色”或“黄色”标签的文档时,我想首先使用这两个标签来获取文档。 到目前为止,我pipe理谷歌,试验和错误:

 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); }); 

它工作得很好,我得到ids的sorting收集:

 [{"_id":"5371355045002fc820a09566","relevance":2},{"_id":"53712fc6c8fcd124216de6cd","relevance":2},{"_id":"5371302ebd4725dc1b908316","relevance":1}] 

现在我会做另一个查询,并要求与这些ID文件 – 但这是我的问题: 可以在一个查询中完成?

是的,你可以像往常一样,当你实际上在_id分组,那么这个值本质上等同于整个文档。 所以这只是将整个文档存储在_id字段下的问题。

你有两种方法取决于你的MongoDB版本,而在MongoDB 2.6之前的版本中,你必须在最初的$project阶段中指定整个文档结构(可以select$match ,这通常是个好主意)在实际操作文档之前,在您的pipe道中:

 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" }} ]) 

当然,在stream水线结束时,您会从_id字段中提取信息,以获取原始结构。 这是可选的,但你通常要这样做。

对于MongoDB 2.6或更高版本,有一个variables可用于stream水线阶段,它在stream水线的这个阶段(称为$$ROOT保存文档的结构,您可以像上面那样访问这个types的快捷方式:

 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" }} ]) 

请记住,为了恢复文档,您仍然需要指定所有必填字段。

我会注意到,因为在这种情况下,您正在使用匹配条件“过滤”文档,并且如前所述,实际上,您应该在stream水线的“头部”使用$match语句进行过滤。 这是聚合框架为了优化查询而select索引的唯一地方,它也减less了不符合条件的文档的数量(假设并非所有的标签都是“黄色”或“蓝色”的)通过剩余的pipe道阶段:

 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" }} ]) 

无论如何,通常应该比试图做另一个查询更有效,而这个查询当然不会像你所做的那样维护你的sorting顺序。