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
使用类型划分对象。这只是一个例子不,没有。我彻底改变了我的制度。