mongodb – 空数组阻止文档出现在查询中

我有几个字段的文档,特别是有一个名为attrs的字段是一个数组.我正在使用聚合管道.

在我的查询中,我感兴趣的是attrs(attributes)字段,如果有任何元素.否则我仍然想得到结果.在这种情况下,我在文档的字段类型之后.

问题是,如果一个文档不包含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,但是如果它们具有它们,则包括属性?

我希望这是有道理的.

最佳答案 您可以在$project阶段使用
$cond运算符将空attr数组替换为包含占位符(如null)的数组,该占位符可用作标记以指示此doc不包含任何attr元素.

所以你要在$unwind之前插入一个这样的额外$project阶段:

    {
        $project: {
            attrs: {$cond: {
               if: {$eq: ['$attrs', [] ]},
               then: [null],
               else: '$attrs'
           }}
        }
    },

唯一需要注意的是,对于那些包含至少一个没有任何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
        }
    }
])
点赞