我的文档中包含一些字段,特别是有一个名为 attrs 的字段是一个数组。我正在使用聚合管道。
在我的查询中,如果其中有任何元素,我对 attrs (属性)字段感兴趣。否则我仍然想得到结果。在这种情况下,我在文档的字段 type 之后。
问题是如果文档中不包含 attrs 字段中的任何元素,它将被过滤掉,我将不会获得其 _id.type 字段,这是我真正想要的查询。
{
aggregate: "entities",
pipeline: [
{
$match: {
_id.servicePath: {
$in: [
/^/.*/,
null
]
}
}
},
{
$project: {
_id: 1,
"attrs.name": 1,
"attrs.type": 1
}
},
{
$unwind: "$attrs"
},
{
$group: {
_id: "$_id.type",
attrs: {
$addToSet: "$attrs"
}
}
},
{
$sort: {
_id: 1
}
}
]
}
所以问题是:如何获得包含所有文档类型的结果,无论他们是否具有 attrs ,但是如果他们拥有这些文档,还包括属性?
我希望这是有道理的。
答案 0 :(得分:4)
您可以在$project
阶段使用$cond
运算符将空attr
数组替换为包含可用作标记的null
占位符的数组attr
数组表示此文档不包含任何$project
元素。
因此,您需要在$unwind
之前插入一个额外的 {
$project: {
attrs: {$cond: {
if: {$eq: ['$attrs', [] ]},
then: [null],
else: '$attrs'
}}
}
},
阶段:
null
唯一需要注意的是,对于那些包含至少一个没有任何attrs
元素的文档的组,您最终会在最终attrs
数组中获得$match
值,所以你需要忽略那些客户端。
示例强>
该示例使用了更改的[
{_id: {type: 1, id: 2}, attrs: []},
{_id: {type: 2, id: 1}, attrs: []},
{_id: {type: 2, id: 2}, attrs: [{name: 'john', type: 22}, {name: 'bob', type: 44}]}
]
阶段,因为您示例中的某个阶段无效。
输入文档
{
"result" : [
{
"_id" : 1,
"attrs" : [
null
]
},
{
"_id" : 2,
"attrs" : [
{
"name" : "bob",
"type" : 44
},
{
"name" : "john",
"type" : 22
},
null
]
}
],
"ok" : 1
}
<强>输出强>
db.test.aggregate([
{
$match: {
'_id.servicePath': {
$in: [
null
]
}
}
},
{
$project: {
_id: 1,
"attrs.name": 1,
"attrs.type": 1
}
},
{
$project: {
attrs: {$cond: {
if: {$eq: ['$attrs', [] ]},
then: [null],
else: '$attrs'
}}
}
},
{
$unwind: "$attrs"
},
{
$group: {
_id: "$_id.type",
attrs: {
$addToSet: "$attrs"
}
}
},
{
$sort: {
_id: 1
}
}
])
汇总命令
{{1}}
答案 1 :(得分:-1)
使用一些if语句和循环。
首先,您的查询应首先选择所有文档。
遍历所有这些
然后,如果属性数大于0,则遍历属性。将它们循环到您认为有用的任何数组或输出中。
如果您愿意,可以使用if语句来清理结果。
答案 2 :(得分:-1)
您应该使用'$或'运算符,以及两个单独的查询:一个用于选择attr值等于所需值的文档,另一个查询用于匹配attr为null或attr键不存在的文档(使用{ {1}}运营商)