【问题标题】:Retrieve matched document from nested array [duplicate]从嵌套数组中检索匹配的文档[重复]
【发布时间】:2018-06-13 12:23:32
【问题描述】:

我正在尝试将所有对象收集到一个嵌套数组中,其中字段spec 等于unknown

每个文档的结构类似于:

{
    "_id" :"5b1e73786f11e421956023c3",
    "subs" : [ 
        {
            "name" : "subrepo1",
            "files" : [ 
                {
                    "name" : ".....",
                    "spec" : "Unknown"
                }, 
                {
                    "name" : ".....",
                    "spec" : "Unknown"
                }
            ]
        },
        {
            "name" : "subrepo2",
            "files" : [ 
                {
                    "name" : "file2",
                    "spec" : "Unknown"
                }, 
                {
                    "name" : ".....",
                    "spec" : "1234"
                }
            ]
        }
    ]
}

我尝试了以下方法,但它不起作用。我认为这是正确的方向,但我可能遗漏了一些重要的东西。

db.col.aggregate([
    {$match: {'subs.files.spec': 'Unknown'}},
    {$project: {
        'subs.files': {$filter: {
            input: '$subs.files',
            //as: 'subs.files',
            cond: {$eq: ['this.spec', 'FunSuite']}
        }},
        //_id: 0
    }}
])

预期的输出将是:(所以只有规格等于未知的文件(而不是其他文件)

{
    "_id" : "5b1e73786f11e421956023c3",
    "subs" : [ 
        {
            "name" : "subrepo1",
            "files" : [ 
                {
                    "name" : ".....",
                    "spec" : "Unknown"
                }, 
                {
                    "name" : ".....",
                    "spec" : "Unknown"
                }
            ]
        },
        {
            "name" : "subrepo2",
            "files" : [ 
                {
                    "name" : "file2",
                    "spec" : "Unknown"
                }
            ]
        }
    ]
}

【问题讨论】:

  • 你的预期输出是什么?
  • @MạnhQuyếtNguyễn 添加输出以使其清晰。

标签: mongodb aggregate


【解决方案1】:

您需要使用$filter aggregation 运算符,它只给出数组中匹配的元素并转义其他元素

db.collection.aggregate([
  {
    $unwind: "$subs"
  },
  {
    $project: {
      "subs.name": "$subs.name",
      "subs.files": {
        $filter: {
          input: "$subs.files",
          as: "file",
          cond: {
            $eq: [
              "$$file.spec",
              "Unknown"
            ]
          }
        }
      }
    }
  },
  {
    $group: {
      _id: "$_id",
      subs: {
        $push: "$subs"
      }
    }
  }
])

上面将给出以下输出

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "subs": [
      {
        "files": [
          {
            "name": ".....",
            "spec": "Unknown"
          },
          {
            "name": ".....",
            "spec": "Unknown"
          }
        ],
        "name": "subrepo1"
      },
      {
        "files": [
          {
            "name": "file2",
            "spec": "Unknown"
          }
        ],
        "name": "subrepo2"
      }
    ]
  }
]

您可以查看结果here

如果您想获取数组中的字段,请从管道中删除 $unwind$replaceRoot 阶段

db.collection.aggregate([
  {
    $unwind: "$subs"
  },
  {
    $project: {
      "subs.name": "$subs.name",
      "subs.files": {
        $filter: {
          input: "$subs.files",
          as: "file",
          cond: {
            $eq: [
              "$$file.spec",
              "Unknown"
            ]
          }
        }
      }
    }
  },
  {
    $unwind: "$subs.files"
  },
  {
    $replaceRoot: {
      newRoot: "$subs.files"
    }
  }
])

上面将给出以下输出

[
  {
    "name": ".....",
    "spec": "Unknown"
  },
  {
    "name": ".....",
    "spec": "Unknown"
  },
  {
    "name": "file2",
    "spec": "Unknown"
  }
]

【讨论】:

  • 这与示例中给出的输入数据不一样,你能改变它吗? (输出很好)
  • @CaptainObvious 我已经更改了输入和输出...请再次检查...
  • 它似乎有效;谢谢。您还可以提供原始输出的查询吗?输出仅包含文件 {name: ..., spec: ....} 因为我也想拥有它。如果你包括那个,我会接受。
【解决方案2】:

试试这个方法:

db.col.aggregate([
    {
        $unwind: '$subs'
    },
    {
        $unwind: '$subs.files'
    },
    {
        $match: {
            'subs.files.spec': 'Unknown'
        }
    }
]);

【讨论】:

  • 这也会返回文件数组中规范不等于未知的元素,这是我不想要的(见输出)
猜你喜欢
  • 2021-05-01
  • 1970-01-01
  • 2012-06-28
  • 1970-01-01
  • 1970-01-01
  • 2022-11-05
  • 1970-01-01
  • 1970-01-01
  • 2017-02-19
相关资源
最近更新 更多