【问题标题】:Mongoose Aggregate with Array of Objects in $lookupMongoose 与 $lookup 中的对象数组聚合
【发布时间】:2021-07-23 04:57:27
【问题描述】:

我有以下收藏:


Collection A:

{
    _id: 123,
    name: "A",
    amount: 2,
    some_other_information: "ttt"
}
{
    _id: 223,
    name: "B",
    amount: 2,
    some_other_information: "ggg"
}

Collection B: 

{
    _id: 123,
    name: "K",
    amount: 2,
    some_other_information: "fff"
}
{
    _id: 2,
    name: "L",
    amount: 2,
    some_other_information: "vvv"
}

Collection: D

{
    _id: 123,
    name: "test",
    items: [
        {
            _id: 1,
            a_id: 123,
            b_id: 1,
            c_id: 123
        },
        {
            _id: 2,
            a_id: 223,
            b_id: 2,
            c_id: 223
        },
        {
            _id: 3,
            a_id: 345,
            b_id: 3
        },
    ]
}

我想将集合 D 与集合 A 与 a_id 聚合在 items 数组中的 D 集合中。

所以我有以下输出:

{
    _id: 123,
    name: "test",
    items: [
        {
            _id: 1,
            a: {
                _id: 123,
                name: "A",
                amount: 2,
                some_other_information: "ttt"
            },
            b: {
                _id: 123,
                name: "K",
                amount: 2,
                some_other_information: "fff"
            },
            c: {
                _id: 123,
                name: "A",
                amount: 2,
                some_other_information: "ttt"
            }
        },
        {
            _id: 2,
            a: {
                _id: 223,
                name: "B",
                amount: 2,
                some_other_information: "ggg"
            },
            b: {
                _id: 2,
                name: "L",
                amount: 2,
                some_other_information: "vvv"
            },
            c: {
                _id: 223,
                name: "B",
                amount: 2,
                some_other_information: "ggg"
            }
        }
    ]
}

我试过了

    const x = await D.aggregate([
        {
          $lookup: {
            from: "A",
            localField: "items.a_id",
            foreignField: "_id",
            as: "a_items",
          },
        },
        {
            $project: {
                _id: 1,
                name: 1,
                items: {
                $map: {
                    input: "$a_items",
                    as: "ri",
                    in: {
                    $mergeObjects: [
                        "$$ri",
                        {
                        $arrayElemAt: [
                            {
                            $filter: {
                                input: "$items",
                                cond: {
                                $eq: [
                                    "$$this._id",
                                    "$$ri.a_id"
                                ]
                                }
                             }
                            },
                            0
                         ]
                        }
                    ],
                    }
                  }
                }
            }
        }]);

但通过这种方式,它不会仅与a_id 聚合。它显示了 A Collection 中的每个项目。更何况不包括c_id(和a_id一样,但不是必须的,所以可以为null)。

所以我不知道该尝试什么了。如果有人可以提供帮助将非常有帮助。

提前致谢!

【问题讨论】:

    标签: node.js arrays mongodb mongoose aggregation-framework


    【解决方案1】:
    • $lookup 与收藏 A
    • $lookup 与集合 B
    • 如果您想要收集 C,您可以添加更多查找
    • $map 迭代 items 数组的循环
    • in 中显示必填字段
    • a 添加一个字段并从 a_items 过滤 items 并获取匹配元素并获取第一个元素
    • b 添加一个字段并从 b_items 过滤 items 并获取匹配元素并获取第一个元素
    • 如果你愿意,你可以添加c
    db.colD.aggregate([
      {
        $lookup: {
          from: "colA",
          localField: "items.a_id",
          foreignField: "_id",
          as: "a_items"
        }
      },
      {
        $lookup: {
          from: "colB",
          localField: "items.b_id",
          foreignField: "_id",
          as: "b_items"
        }
      },
      {
        $project: {
          _id: 1,
          name: 1,
          items: {
            $map: {
              input: "$items",
              as: "i",
              in: {
                _id: "$$i._id",
                a: {
                  $arrayElemAt: [
                    {
                      $filter: {
                        input: "$a_items",
                        cond: { $eq: ["$$this._id", "$$i.a_id"] }
                      }
                    },
                    0
                  ]
                },
                b: {
                  $arrayElemAt: [
                    {
                      $filter: {
                        input: "$b_items",
                        cond: { $eq: ["$$this._id", "$$i.b_id"] }
                      }
                    },
                    0
                  ]
                }
              }
            }
          }
        }
      }
    ])
    

    Playground

    【讨论】:

    • 嘿,成功了!我还有一个问题。有没有办法可以限制在 A (colA) 中显示哪些属性?因为目前它显示了集合中的每个属性,我只想要名称和数量。
    • 最后添加第二个 $project 阶段并显示所有必填字段{ $project: { "items.a._id": 1 } }
    猜你喜欢
    • 1970-01-01
    • 2021-08-09
    • 1970-01-01
    • 2020-09-14
    • 2022-01-11
    • 2021-02-01
    • 2020-04-03
    • 2020-07-02
    • 2019-01-21
    相关资源
    最近更新 更多