我使用的是mongo文档中的示例,但我对其进行了一些更改:
db.books.aggregate(
[
{ $group : { _id : "$genre", books: { $push: "$$ROOT" } } }
]
)
此查询将按流派返回一系列图书。
我想对其进行一些自定义,这样我就不会得到额外的数据。以下示例将是一个虚拟示例,但我很好奇它是否可以在mongo中实现。我希望我的汇总返回一组数组,如果genre
为“悲剧”,则只会获取一本书,并且会有一个booksCount
字段,而在所有其他情况下,books
会是一个数组,就不会有booksCount
。
所以聚合结果看起来像这样:
[
{ _id: '_id of tragedy genre', book: {some book}, booksCount: some int },
{ _id: '_id of some other genre', books: [books] },
...
]
所以我希望组根据某些条件具有不同的键
答案 0 :(得分:1)
一种实现方法是使用$facet
聚合管道阶段。此阶段使我们可以使用相同的输入文档创建多个管道。在这种情况下,悲剧类型有一个管道,所有其他类型都有一个管道。为了获得所需的输出,我们需要合并两个管道阶段。从文档中:
每个子管道在输出文档中都有自己的字段,其结果存储为文档数组。
因为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"
}
]
}