基于数组中子对象属性的MongoDB聚合管道过滤器

基于数组中子对象属性的MongoDB聚合管道过滤器,mongodb,mongodb-query,nosql,aggregation-framework,Mongodb,Mongodb Query,Nosql,Aggregation Framework,具有以下结构的给定文档: { 'id': 1, name: 'bob', type: 'foo', children: [{'id': 2}, {'id': 3}]} { 'id': 2, name: 'bob', type: 'foo' } { 'id': 3, name: 'bob', type: 'bar' } { 'id': 4, name: 'bob', type: 'foo', children: [{'id': 5}, {'id': 6}]} { 'id': 5, name: 'b

具有以下结构的给定文档:

{ 'id': 1, name: 'bob', type: 'foo', children: [{'id': 2}, {'id': 3}]}
{ 'id': 2, name: 'bob', type: 'foo' }
{ 'id': 3, name: 'bob', type: 'bar' }
{ 'id': 4, name: 'bob', type: 'foo', children: [{'id': 5}, {'id': 6}]}
{ 'id': 5, name: 'bob', type: 'foo' }
{ 'id': 6, name: 'bob', type: 'foo' }
我如何编写聚合管道查询来查找所有文档,如果它们有子文档,那么所有子文档的类型都是
foo
(父文档的类型是'foo')

补充说明:

  • 子对象
    是一个对象数组,其属性引用同一集合中的其他文档
  • 并非所有文档都有子文档
  • 更改文档结构不是一个选项
  • 我已经研究了$unwind和$lookup,但是这会导致许多文档,我只希望在这之后有父文档

在对聚合管道API进行了一些额外的尝试之后,下面是一个潜在的解决方案

这些步骤是:

  • 首先,根据
    类型
    标准,
    $match
    ,以确保管道中随后仅使用具有适当
    类型
    的父文档
  • 对子文档执行简单的
    $lookup
    。尽管这似乎没有明确记录,
    $lookup
    可以毫不费力地使用数组中嵌套对象的属性
  • 对结果文档执行最终匹配,使用
    $elemMatch
    和一些否定来实现所需的效果
  • 下面是使用Robo3T时的情况(应该很容易翻译成其他查询客户端):

    注意:在这种特殊情况下,
    id
    只是一个占位符,用于连接任何文档,而不是“官方”
    \u id
    mongo字段

    这将排除文档1和3,因为3有一个“bar”类型,而1包含它


    这可能不是一个最佳的解决方案,我还没有在大型数据集上测试过它。另外,使用
    $elemMatch
    的最终匹配非常混乱,因此欢迎对此提出改进建议。

    包括您提出的查询及其结果。我没有有效的查询,因此提出了这个问题。我最接近的方法是进行简单的查找,但是要使匹配对每个嵌套文档都起作用并没有成功。我不清楚这是正确的方法还是其他方法更有效。即使这样做有效,我也不知道这是最优的还是有更简单的方法。我只是不具备mongodb的专业知识。请检查并添加您的查询和结果。@D.SM别担心,我已经用找到的解决方案添加了我自己的答案。我希望它将来对其他人有用。尽管如此,请随意否决。我仍然不觉得我无数次失败的迭代会有助于澄清这个问题,相反,它们会使问题变得更加复杂和混乱。做某事有无数错误的方法,我尝试了很多。
    db.getCollection('items').aggregate([
        { $match : { "type": "foo" } },
        {
            $lookup: {
                from: "items",
                localField: "children.id",
                foreignField: "id",
                as: "items"
            }
        },
        {
            $match : { 
                "items": {
                    $not: {
                        $elemMatch: {
                            "type": { $ne: "foo" }
                        }
                    }
                }
            }
        }
    ])