空数组阻止文档出现在查询中 [英] Empty array prevents document to appear in query
问题描述
我的文档有几个字段,尤其是有一个名为 attrs 的字段,它是一个数组.我正在使用聚合管道.
I have documents that have a few fields and in particular the have a field called attrs that is an array. I am using the aggregation pipeline.
在我的查询中,如果其中包含任何元素,我会对 attrs (属性)字段感兴趣.否则我仍然想要得到结果.在这种情况下,我在文档的 type 字段之后.
In my query I am interested in the attrs (attributes) field if there are any elements in it. Otherwise I still want to get the result. In this case I am after the field type of the document.
问题在于,如果文档的 attrs 字段中不包含任何元素,它将被过滤掉,而我不会得到其 _id.type 字段,这是我真正想要的查询.
The problem is that if a document does not contain any element in the attrs field it will be filtered away and I won't get its _id.type field, which is what I really want from this query.
{
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 ,但包括属性(如果它们具有属性的话)?
So the question is: how can I get a result containing all documents types regardless of their having attrs, but including the attributes in case they have them?
我希望这是有道理的.
推荐答案
You can use the $cond
operator in a $project
stage to replace the empty attr
array with one that contains a placeholder like null
that can be used as a marker to indicate that this doc doesn't contain any attr
elements.
因此,您需要在$unwind
之前的位置插入一个额外的$project
阶段:
So you'd insert an additional $project
stage like this right before the $unwind
:
{
$project: {
attrs: {$cond: {
if: {$eq: ['$attrs', [] ]},
then: [null],
else: '$attrs'
}}
}
},
唯一的警告是,对于包含至少一个文档且没有任何attrs
元素的组,您将在最终的attrs
数组中以null
值结尾,因此您需要忽略这些客户端-一侧.
The only caveat is that you'll end up with a null
value in the final attrs
array for those groups that contain at least one doc without any attrs
elements, so you need to ignore those client-side.
示例
该示例使用一个更改的$match
阶段,因为示例中的那个无效.
The example uses an altered $match
stage because the one in your example isn't valid.
输入文档
[
{_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
}
}
])
这篇关于空数组阻止文档出现在查询中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!