【问题标题】:Nested Lookup and filtering嵌套查找和过滤
【发布时间】:2021-03-03 17:13:39
【问题描述】:

我有以下收藏

用户

[
{
  id : 'acd-1234',
  name : 'some name',
  profile_id : 1,
  is_graduate: true, 
  children: [
    { class: 'User', id: 'abcd-123'},
    { class: 'User', id: 'bcd-33'}
  ]
},
{
  id: 'abcd-123',
  name : 'jhon',
  profile_id : 2
  is_graduate: true, 
},
{
  id: 'bcd-123',
  name : 'jhon due',
  profile_id : 3,
  is_graduate: false 
}
] 

个人资料

[
  {
    id: 1,
    address: 'some address'  
  },
  {
    id: 2,
    address: 'some other address'  
  },
  {
    id: 3,
    address: 'some other other address'  
  }

]

我需要的最终输出是(父母只有研究生)

[
  {
    id: 'acd-1234',
    name: 'some name',
    is_graduate: true, 
    profile : {
       id: 1,
       address: "some address"
    },
    children: [
       {
         id: "abcd-123",
         name: "jhon",
         is_graduate: true, 
         profile: {
           id: 2,
           address: "some other address" 
         }
       }
    ] 
  }
]

我真正陷入困境的地方是

  1. 进行嵌套查找。显示所有孩子的个人资料
  2. 对孩子应用过滤

来自 mongo 的以下错误不允许我使用带有 localField 的管道 $lookup with 'pipeline' may not specify 'localField' or 'foreignField'

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    试试这个:

    db.users.aggregate([
        {
            $lookup: {
                from: "profile",
                let: { id: "$profile_id" },
                pipeline: [
                    {
                        $match: {
                            $expr: { $eq: ["$id", "$$id"] }
                        }
                    }
                ],
                as: "profile"
            }
        },
        { $unwind: "$profile" },
        {
            $lookup: {
                from: "users",
                let: {
                    id: { $ifNull: ["$children.id", []] }
                },
                pipeline: [
                    {
                        $match: {
                            $expr: { $in: ["$id", "$$id"] }
                        }
                    },
                    {
                        $lookup: {
                            from: "profile",
                            localField: "profile_id",
                            foreignField: "id",
                            as: "profile"
                        }
                    },
                    { $unwind: "$profile" }
                ],
                as: "children"
            }
        }
    ]);
    

    如果您只想显示非空children,则在最后一个$lookup 之后添加$match 阶段:

    {
        $match: {
            $expr: {
                $gt: [{ $size: "$children" }, 0]
            }
        }
    }
    

    【讨论】:

    • 谢谢。它解决了这个问题。但是,当我与大约 30k 用户一起运行此查询时,会花费很多时间。显然,实际的集合有更多的字段和查找(我也有必要的索引)。我怀疑这是因为我们正在与用户一起加入用户。我们能否以某种方式有两个单独的阶段,一个仅用于查找子级,然后在下一阶段过滤并与用户执行嵌套查找(这将减少通过阶段的数据量)。
    • 你是对的。你可以在各个地方添加$match stage,以过滤掉不需要的文档进入下一个stage。
    • 我知道匹配的事情。但看起来只有这个特定的加入(用户*用户)大部分时间都在占用。所以你有什么建议。比如我们如何分离出 JOINING 部分并在下一阶段进行查找和过滤。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-09
    • 2018-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多