我使用的是从我已经改变了一点蒙戈文档的例子:
db.books.aggregate(
[
{ $group : { _id : "$genre", books: { $push: "$$ROOT" } } }
]
)
这个查询将返回类型书籍的数组。
我想定制它一下,这样我就不会得到额外的数据。下面的例子将是一个虚拟的,但我很好奇,如果它可以在蒙戈实施。我希望我的聚集回到这里,如果genre
是“悲剧”只有1本书会被获取并会有一个booksCount
场并在所有其他情况下books
将是一个数组,也不会有一个booksCount
组的阵列。
因此,聚合结果会是这个样子:
[
{ _id: '_id of tragedy genre', book: {some book}, booksCount: some int },
{ _id: '_id of some other genre', books: [books] },
...
]
所以,我想小组有根据一些条件不同的密钥
这样做的一个方法是使用$facet
聚集流水线阶段。这个阶段允许我们创建具有相同的输入文档的多个管道。在这种情况下,我们对悲剧体裁一个管道,另一个用于所有其他类型。为了得到你想要的输出,我们需要合并两个流水线阶段。从文档:
每个子流水线具有这样的结果存储为文件的阵列输出文档中其自己的领域。
由于小舞台返回的每个管道文件的数组,我们需要:拼接这些阵列在一起,放松身心的结果数组,这样每一个元素是它自己的文件,然后替换每个文档的根摆脱不必要的关键。
假设你有下列文件:
db.books.insertMany([{
genre: "Tragedy",
title: "Romeo and Juliet"
}, {
genre: "Tragedy",
title: "Titanic"
}, {
genre: "Comedy",
title: "Hitchhikers Guide to the Galaxy"
}, {
genre: "Comedy",
title: "Blazing Saddles"
}, {
genre: "Thriller",
title: "Shutter Island"
}, {
genre: "Thriller",
title: "Hannibal"
}])
然后你可以使用下面的查询:
db.books.aggregate([{
$facet: {
tragedy: [{
$match: {genre: "Tragedy"}
}, {
$group: {
_id: "$genre",
books: {$push: "$$ROOT"}
}
}, {
$project: {
book: {$arrayElemAt: ["$books", 1]},
booksCount: {$size: "$books"}
}
}],
other: [{
$match: {
genre: {$ne: "Tragedy"}
}
}, {
$group: {
_id: "$genre",
books: {$push: "$$ROOT"}
}
}]
}
}, {
$project: {
documents: {$concatArrays: ["$tragedy", "$other"]}
}
}, {
$unwind: "$documents"
}, {
$replaceRoot: {newRoot: "$documents"}
}])
生产:
{
"_id" : "Tragedy",
"book" : {
"_id" : ObjectId("5c59f15bc59454560b36a5c7"),
"genre" : "Tragedy",
"title" : "Titanic"
},
"booksCount" : 2
}
{
"_id" : "Thriller",
"books" : [
{
"_id" : ObjectId("5c59f15bc59454560b36a5ca"),
"genre" : "Thriller",
"title" : "Shutter Island"
},
{
"_id" : ObjectId("5c59f15bc59454560b36a5cb"),
"genre" : "Thriller",
"title" : "Hannibal"
}
]
}
{
"_id" : "Comedy",
"books" : [
{
"_id" : ObjectId("5c59f15bc59454560b36a5c8"),
"genre" : "Comedy",
"title" : "Hitchhikers Guide to the Galaxy"
},
{
"_id" : ObjectId("5c59f15bc59454560b36a5c9"),
"genre" : "Comedy",
"title" : "Blazing Saddles"
}
]
}