Arrays mongoose聚合如何将多个集合映射到一个数组中

Arrays mongoose聚合如何将多个集合映射到一个数组中,arrays,mongodb,dictionary,mongoose,aggregate,Arrays,Mongodb,Dictionary,Mongoose,Aggregate,我有四种不同的收藏。其中三个连接到一个: Collection_A = { _id: 1 name: A includes: [ { _id: 1, includes_id: 222, }, { _id: 2, includes_id: 333 } ] } Collection_B = { _i

我有四种不同的收藏。其中三个连接到一个:

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可以在includes对象中包含集合B、C和D。它至少包括一个集合

所以在集合A的includes对象中是includes_id,它是集合B、C和D中的_id。 集合A中的_id是集合B、C和D中的参考id

我现在的问题是,聚合只接受最后一个映射的集合

我现在的代码如下:

     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,
                    ],
                },
              },
            },
          },
        },
      ]);

{
    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
                },
            ]
        }
    ]
}
我试图使$lookup在每次查找时都相同,但它只使用最后一次查找的数据,其他数据显示为null。 所以我将$lookup设置为唯一,并在map中放置了两个插件,但最后一次查找的数据也显示了出来,其他的则为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_列表

我期望的输出如下所示:

     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,
                    ],
                },
              },
            },
          },
        },
      ]);

{
    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
帮助对传入数据进行分类

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",[] ]
          }
        }
      }
    }
  }
])
工作


注意:我觉得这是一种你遵循的反模式。如果您正处于项目的早期阶段,如果我没有弄错的话,最好更改结构。

您对如何更好地完成这项工作有什么建议吗?@soptro我不知道您正在使用的域模型。但是您可以使用OOP概念,比如继承。例如:
人类扩展动物
宠物扩展动物
。所以
动物
姓名、年龄、类型//人类或宠物
<代码>人类拥有
语言
<代码>宠物有
一些其他字段
。由于两者都是扩展表单
Animal
,因此可以将两者放在一个集合中。在后端检索时,可以使用
instanceOf
使用
类型划分对象。这只是一个例子不,没有。我彻底改变了我的制度。