猫鼬聚合如何将多个集合映射到一个数组中 [英] mongoose aggregate how to map multiple collections into one Array

查看:60
本文介绍了猫鼬聚合如何将多个集合映射到一个数组中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有四个不同的系列.从哪三个连成一个:

I have four different collections. From which three are connected to one:

Collection_A = {
    _id: 1
    name: A
    includes: [
        {
            _id: 1,
            includes_id: 222,
        },
        {
            _id: 2,
            includes_id: 333
        }
    ] 
}

Collection_B = {
    _id: 222,
    type: Computer,
    name: Computer,
    ref_id: 1
}

Collection_C = {
    _id: 333,
    type: Human,
    name: Human,
    ref_id: 1
}

Collection_D = {
    _id: 444,
    type: Animal,
    name: Animal,
    ref_id: 1
}

所以集合 A 可以在包含对象中包含集合 B、C 和 D.它包括至少一个集合.

So collection A can include Collection B, C and D in the includes object. It includes minimum one of the collections.

所以在集合A的includes对象中是includes_id,它是集合B、C和D中的_id.集合 A 中的 _id 是集合 B、C 和 D 中的 ref_id.

So in the includes object in Collection A is the includes_id, which is the _id in Collection B, C and D. The _id in Collection A is the ref_id in Collection B, C and D.

我现在的问题是,该聚合只需要最后一个映射的集合.

What my problem right now is, that aggregate takes only the last mapped collection.

我现在的代码如下:

     Collection_A.aggregate([
        {
          $lookup: {
            from: "collectionb",
            localField: "includes.includes_id",
            foreignField: "_id",
            as: "colb",
          },
        },
        {
          $lookup: {
            from: "collectionc",
            localField: "includes.includes_id",
            foreignField: "_id",
            as: "colc",
          },
        },
        {
          $project: {
            _id: 1,
            status: 1,
            type: 1,
            includes_list: {
              $map: {
                input: "$includes",
                as: "i",
                in: {
                  $arrayElemAt: [
                        {
                        $filter: {
                            input: "$colb",
                            cond: {
                            $eq: ["$$this._id", "$$i.includes_id"],
                            },
                        },
                        },
                        0,
                    ],
                    $arrayElemAt: [
                        {
                        $filter: {
                            input: "$colc",
                            cond: {
                            $eq: ["$$this._id", "$$i.includes_id"],
                            },
                        },
                        },
                        0,
                    ],
                },
              },
            },
          },
        },
      ]);

我试图在每次查找时都使 $lookup 相同,但它只使用最后一次查找的数据,而其他数据显示为空.所以我将 $lookup 设置为唯一的,并在 map 中放入了两个 in,但也显示了最后查找的数据,而其他的为 null.

I tried to make the $lookup as the same on every lookup, but so it only took the last looked up data, and the others where shown as null. So I made $lookup as unique, and put two ins in map, but then also the last looked up data was shown, and the others where null.

当我做这样的映射时:

includes_list: {
    $map: {
    input: "$icludes",
    as: "i",
    in: {
        {
            Col_A : {
            $arrayElemAt: [
                {
                    $filter: {
                        input: "$A",
                        cond: {
                        $eq: ["$$this._id", "$$i.includes"],
                        },
                    },
                },
                0,
            ],
            },
            Col_B : {
            $arrayElemAt: [
                {
                    $filter: {
                        input: "$B",
                        cond: {
                        $eq: ["$$this._id", "$$i.includes"],
                        },
                    },
                },
                0,
            ],
            }
        }
    },
    },
}

它有效.但没有正确的输出,因为我需要在一个数组中包含 includes_list.

It workes. But not with the right output, because I need includes_list within one array.

我想要的输出如下:

{
    includes: [
        {
            _id: 1,
            name: Computer,
            includes_list: [
                {
                    _id: 222,
                    type: Computer,
                    name: Computer,
                    ref_id: 1
                },
                {
                    _id: 333,
                    type: Human,
                    name: Human,
                    ref_id: 1
                },
            ]
        },
        {
            _id: 2,
            name: Animal,
            includes_list: [
                {
                    _id: 333,
                    type: Human,
                    name: Human,
                    ref_id: 2
                },
            ]
        }
    ]
}

非常感谢您的帮助!

推荐答案

对于这种情况,$facet 帮助对传入的数据进行分类

For this kind of situation, $facet help to categorize the incoming data

db.Collection_A.aggregate([
  { $unwind: "$includes },
  {
    "$facet": {
      "joinB": [            
        {
          "$lookup": {
            "from": "Collection_B", "localField": "includes.includes_id",
            "foreignField": "_id", "as": "includes.includes_list"
          }
        },
        {
          "$group": {
            "_id": "$_id",
            "name": { "$first": "$name" },
            includes: { $push: "$includes" }
          }
        }
      ],
      "joinC": [            
        {
          "$lookup": {
            "from": "Collection_C", "localField": "includes.includes_id",
            "foreignField": "_id", "as": "includes.includes_list"
          }
        },
        {
          "$group": {
            "_id": "$_id",
            "name": { "$first": "$name" },
            includes: { $push: "$includes" }
          }
        }
      ],
      "joinD": [
        {
          "$lookup": {
            "from": "Collection_D", "localField": "includes.includes_id",
            "foreignField": "_id", "as": "includes.includes_list"
          }
        },
        {
          "$group": {
            "_id": "$_id",
            "name": { "$first": "$name" },
            includes: { $push: "$includes" }
          }
        }
      ],
      
    }
  },
  {
    $project: {
      combined: {
        "$concatArrays": [ "$joinB", "$joinC", "$joinD" ]
      }
    }
  },
  { "$unwind": "$combined" },
  {
    "$replaceRoot": { "newRoot": "$combined" }
  },
  {
    "$project": {
      _id: 1,
      name: 1,
      includes: {
        $filter: {
          input: "$includes",
          cond: {
            $ne: [ "$$this.includes_list",[] ]
          }
        }
      }
    }
  }
])

工作 Mongo 游乐场

注意:我觉得这是你遵循的一种反模式.如果你在项目的早期阶段,如果我没记错的话最好改变结构.

Note: I feel this is kind of Anti pattern you follow. If you are in early stage of the project, better change the structure if I'm not mistaken.

这篇关于猫鼬聚合如何将多个集合映射到一个数组中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆