是的,当您实际分组时,您可以像往常一样,_id
然后该值基本上等同于整个文档。因此,只需将整个文档存储在该_id
字段下即可。
根据您的 MongoDB 版本,您有几种方法,在 MongoDB 2.6 之前的版本中,您必须在管道的初始$project
阶段指定整个文档结构(这可能会出现在$match
通常是一个好主意的 a 之后)您实际上操纵了文档:
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"
}}
])
无论如何,这通常比尝试执行另一个查询更有效,这当然不会以您所做的方式维护您的排序顺序。