MongoDB 聚合在空数组上展开

Joh*_*ohn 3 mongodb aggregation-framework

我在 MongoDB 中有一个文档集合,其中每个文档都有一个包含数组的子文档。

{
  _id: <id>
  key1: "value1",
  key2: "value2",
  ...
  versions: [
    { version: 2, key1: <othervalue2>, key2: <othervalue2>}
    { version: 1, key1: <othervalue2>, key2: <othervalue2>}
  ]
}
Run Code Online (Sandbox Code Playgroud)

我想查询集合并返回文档及其所有字段,以及与某些参数匹配的数组元素(或不匹配时的空数组)。使用我当前的代码,只有当数组中至少有一个匹配的元素时,我才能得到结果。

我使用这些参数进行聚合:

{$match: {_id: <someID>}},
{$unwind: '$versions'},
{$match: {'versions.version': {$gte: <version>}}},
{$group: {_id: '$_id', key1: {$first: '$key1'}, ..., 'versions': {$push: '$versions'}}
Run Code Online (Sandbox Code Playgroud)

例如,查询 arrayelement.version >= 2 应该返回的位置(这适用于当前代码):

{
  _id: <id>
  key1: "value1",
  key2: "value2",
  ...
  versions: [
    { version: 2, key1: <othervalue2>, key2: <othervalue2>}
  ]
}
Run Code Online (Sandbox Code Playgroud)

并查询 arrayelement.version >= 4 应返回的位置:

{
  _id: <id>
  key1: "value1",
  key2: "value2",
  ...
  versions: []
}
Run Code Online (Sandbox Code Playgroud)

我见过的解决方案都没有解决即使数组为空也返回对象的问题。这甚至可能吗?

zer*_*323 5

您可以检查版本数组是否为空,如果是,则添加一些占位符,例如空文档。省略管道的其余部分,它可能是这样的:

[
    {
        "$project" : {
            "versions" : {
                "$cond" : {
                    "if" : {"$eq" : [{"$size" : "$versions" }, 0]},
                    "then" : [{ }],
                    "else" : "$versions"
                }
            },
            "_id" : 1
        }
    },
    {
        "$unwind" : "$versions"
    }
]
Run Code Online (Sandbox Code Playgroud)

请记住,{$match: {'versions.version'}}在您的管道中会将其过滤掉,因此您必须调整这部分。