如何编写聚合管道以将合并文档作为文档插入MongoDB上的新字段获取?
我是MongoDB的新手,我将用一个例子来说明我的问题。情景:如何编写聚合管道以将合并文档作为文档插入MongoDB上的新字段获取?,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我是MongoDB的新手,我将用一个例子来说明我的问题。情景: 收藏3本 收藏1 { "_id": 1, "idLocal": 1023, "idType": 21 }, { "_id": 2, "idLocal": 1029, "idType": 21 }, { "_id": 3, &
- 收藏3本李>
{
"_id": 1,
"idLocal": 1023,
"idType": 21
},
{
"_id": 2,
"idLocal": 1029,
"idType": 21
},
{
"_id": 3,
"idLocal": 923,
"idType": 22
}
收藏2
{
"_id": 1,
"idLOp": 1,
"idType": 21
},
{
"_id": 2,
"idOp": 5,
"idType": 21
}
{
"_id": 3,
"idOp": 1,
"idType": 12
}
因此,要在集合_3上插入新文档,我需要创建一个新文档,附加集合_1和集合_2中的文档,并满足以下条件:
idLocal (Collection_1) == idLocal (New doc to insert) // get desired doc from Collection_1
idOp (Collection_2) == idOp (New doc to insert) AND idType (Collection_1 ) == idType (Collection_2) // get desired doc from Collection_2
要插入的样本文档
{
"_id": 5,
"idOp": 1,
"idLocal": 1023
}
收藏3
// new doc saved at Collection_3 result desired:
{
"_id": 5,
"idOP": 1,
"idLocal": 1023,
"Collection_1_doc": {
"_id": 1,
"idLocal": 1023,
"idType": 21
},
"Collection_2_doc": {
"_id": 1,
"idLOp": 1,
"idType": 21
}
}
那么,我如何使用MongoDB管道工具来实现它呢?我以前从未编写过管道,也不知道如何使用函数。您不能编写一个聚合管道,因为MongoDb 4.2只在管道中使用这些阶段-
- $addFields
- $set
- $project
- 美元未结算
- $replaceRoot
- $replacetwith
因此,一种方法如下- 第一步是获取链接数据,首先对
collection_1
和collection_2
中的链接文档进行聚合,然后使用运算符获取找到的第一个文档
var doc3 = {
"_id": 5,
"idOp": 1,
"idLocal": 1023
};
db.Collection_1.aggregate([
{
$match: {
idLocal: doc3.idLocal
}
},
{
$lookup: {
from: 'Collection_2',
pipeline: [
{
$match: {
$expr: {
$eq: [ "$idOp", doc.idOp ]
}
}
}
],
as: "Collection_2_data"
}
},
{
$project: {
_id: 0,
Collection_1: {
_id: '$_id',
idLocal: '$idLocal',
idType: '$idType'
},
Collection_2: {
$arrayElemAt: [
'$Collection_2_data',
0
]
}
}
}
]);
,即-
[
{
"Collection_1": {
"_id": 1,
"idLocal": 1023,
"idType": 21
},
"Collection_2": {
"_id": 3,
"idOp": 1,
"idType": 12
}
}
]
由于聚合查询的结果始终包装在数组中,因此请安全地访问第一个索引,并将其附加到doc3
中并插入它
假设您使用的是猫鼬,这就是上述想法的代码-
const mongoose = require('mongoose');
(async () => {
try {
let doc3 = {
_id: 5,
idOp: 1,
idLocal: 1023
};
const pipeline = [
{
$match: {
idLocal: doc3.idLocal
}
},
{
$lookup: {
from: 'Collection_2',
pipeline: [
{
$match: {
$expr: {
$eq: [ "$idOp", doc.idOp ]
}
}
}
],
as: "Collection_2_data"
}
},
{
$project: {
_id: 0,
Collection_1: {
_id: '$_id',
idLocal: '$idLocal',
idType: '$idType'
},
Collection_2: {
$arrayElemAt: [
'$Collection_2_data',
0
]
}
}
}
];
const linkedDocsResult = await Collection_1.aggregate(pipeline).exec();
if (linkedDocsResult.length) {
doc3 = Object.assign(Object.create(null), doc3, linkedDocsResult[0]);
}
await Collection_3.create(doc3);
} catch (err) {
console.error(err);
}
})();
您可以尝试使用“我不知道使用管道”,因此您要插入文档或将文档作为投影返回?新文档必须保存在集合_3。恐怕您无法一次性完成,您需要两个操作,首先获取链接数据,然后插入它。回答很好。这对我来说有点复杂,否则,我只能获取文档的ID来插入一个新文档,而不是复制整个文档?