我有一个包含以下结构文档的集合:
{
"_id" : ObjectId("547b4b4ba7d3aef3bdbc5e1c"),
"title" : "article1",
"comments" : [
{
"text" : "first comment",
"createdAt" : ISODate("2014-11-30T16:52:24.032Z")
}
],
"pictures" : [
{
"url" : "http://example.com/1.jpg",
"isPrimary" : false
},
{
"url" : "http:example.com/2.jpg",
"isPrimary" : true
},
{
"url" : "http://example.com/3.jpg"
}
]
}
我需要使用单个查询提取所有文档并排除非主要图片。即输出应该是:
{
"_id" : ObjectId("547b4b4ba7d3aef3bdbc5e1c"),
"title" : "article1",
"comments" : [
{
"text" : "first comment",
"createdAt" : ISODate("2014-11-30T16:52:24.032Z")
}
],
"pictures" : [
{
"url" : "http:example.com/2.jpg",
"isPrimary" : true
}
]
}
如果"图片"甚至更好将包含文档而不是数组:
...
"pictures" : {
"url" : "http:example.com/2.jpg",
"isPrimary" : true
}
...
我尝试了聚合和$ redact,但它不起作用,因为文档和评论子文档没有' isPrimary'字段。
答案 0 :(得分:0)
在Aggregation Framework中使用$unwind
:
db.collection.aggregate([
{ $project: {
_id: 1,
title: 1,
comments: 1,
pictures: {
$cond : [
// if pictures is null or does not exists, project it to []
{ $eq : [ { $ifNull: [ "$pictures", [] ] } , [] ] },
// if pictures is [] then project it to a list with one fake empty picture with isPrimary set to true
[ { isPrimary: true, _empty: true } ],
// otherwise project it to just the original pictures property
"$pictures"
] }
} },
{ $unwind: "$pictures" },
{ $match: { "pictures.isPrimary": true } },
{ $group: {
_id: "$_id",
title: { $first: "$title" },
comments: { $first: "$comments" },
picture: { $first: "$pictures" }
} },
{ $project: {
_id: 1,
title: 1,
comments: 1,
// filter out the fake isPrimary pictures that were added in the initial projection
picture: { $cond: [ { $eq: [ "$picture._empty", true ] }, {}, "$picture" ] }
} }
])