如何将 Mongo 数据库聚合结果附加到现有集合?
How do I append Mongo DB aggregation results to an existing collection?
我正在尝试使用以下代码对现有 Mongo 数据库集合执行多次插入
db.dados_meteo.aggregate( [
{ $match : { "POM" : "AguiardaBeira" } },
{ $project : {
_id : { $concat: [
"0001:",
{ $substr: [ "$DTM", 0, 4 ] },
{ $substr: [ "$DTM", 5, 2 ] },
{ $substr: [ "$DTM", 8, 2 ] },
{ $substr: [ "$DTM", 11, 2 ] },
{ $substr: [ "$DTM", 14, 2 ] },
{ $substr: [ "$DTM", 17, 2 ] }
] },
"RNF" : 1, "WET":1,"HMD":1,"TMP":1 } },
{ $out : "dados_meteo_reloaded" }
] )
但每次我更改 $match 参数并进行新聚合时,Mongo DB 会删除以前的文档并插入新结果。
你能帮帮我吗?
简短的回答是"you can't":
If the collection specified by the $out operation already exists, then upon completion of the aggregation, the $out stage atomically replaces the existing collection with the new results collection. The $out operation does not change any indexes that existed on the previous collection. If the aggregation fails, the $out operation makes no changes to the pre-existing collection.
作为一种解决方法,您可以在聚合后立即将 $out
指定的集合文档复制到 "permanent" 集合,方法有以下几种(虽然没有一种是理想的):
- copyTo() 是最简单的,注意警告。不要为了小效果而使用其他。
- 使用 JS:
db.out.find().forEach(function(doc) {db.target.insert(doc)})
- 使用 mongoexport / mongoimport
这不是有史以来最漂亮的东西,但作为另一种替代语法(来自 post-processing archive/append 操作)...
db.targetCollection.insertMany(db.runCommand(
{
aggregate: "sourceCollection",
pipeline:
[
{ $skip: 0 },
{ $limit: 5 },
{
$project:
{
myObject: "$$ROOT",
processedDate: { $add: [new ISODate(), 0] }
}
}
]
}).result)
我不确定这与 forEach 变体相比如何,但我发现它阅读起来更直观。
开始Mongo 4.2
,新的$merge
聚合运算符(类似于$out
)允许合并 聚合管道的结果到指定的集合:
鉴于此输入:
db.source.insert([
{ "_id": "id_1", "a": 34 },
{ "_id": "id_3", "a": 38 },
{ "_id": "id_4", "a": 54 }
])
db.target.insert([
{ "_id": "id_1", "a": 12 },
{ "_id": "id_2", "a": 54 }
])
$merge
聚合阶段可以这样使用:
db.source.aggregate([
// { $whatever aggregation stage, for this example, we just keep records as is }
{ $merge: { into: "target" } }
])
生产:
// > db.target.find()
{ "_id" : "id_1", "a" : 34 }
{ "_id" : "id_2", "a" : 54 }
{ "_id" : "id_3", "a" : 38 }
{ "_id" : "id_4", "a" : 54 }
请注意,$merge
运算符附带 many options 以指定如何合并与现有记录冲突的插入记录。
在这种情况下(使用默认选项),这:
保留目标集合的现有文档({ "_id": "id_2", "a": 54 }
就是这种情况)
将聚合管道输出中的文档不存在时插入到目标集合中(基于 _id
- 这是 { "_id" : "id_3", "a" : 38 }
的情况)
在聚合管道生成目标集合中存在的文档时替换目标集合的记录(基于_id
- 这是{ "_id": "id_1", "a": 12 }
替换为[=的情况23=])
我正在尝试使用以下代码对现有 Mongo 数据库集合执行多次插入
db.dados_meteo.aggregate( [
{ $match : { "POM" : "AguiardaBeira" } },
{ $project : {
_id : { $concat: [
"0001:",
{ $substr: [ "$DTM", 0, 4 ] },
{ $substr: [ "$DTM", 5, 2 ] },
{ $substr: [ "$DTM", 8, 2 ] },
{ $substr: [ "$DTM", 11, 2 ] },
{ $substr: [ "$DTM", 14, 2 ] },
{ $substr: [ "$DTM", 17, 2 ] }
] },
"RNF" : 1, "WET":1,"HMD":1,"TMP":1 } },
{ $out : "dados_meteo_reloaded" }
] )
但每次我更改 $match 参数并进行新聚合时,Mongo DB 会删除以前的文档并插入新结果。
你能帮帮我吗?
简短的回答是"you can't":
If the collection specified by the $out operation already exists, then upon completion of the aggregation, the $out stage atomically replaces the existing collection with the new results collection. The $out operation does not change any indexes that existed on the previous collection. If the aggregation fails, the $out operation makes no changes to the pre-existing collection.
作为一种解决方法,您可以在聚合后立即将 $out
指定的集合文档复制到 "permanent" 集合,方法有以下几种(虽然没有一种是理想的):
- copyTo() 是最简单的,注意警告。不要为了小效果而使用其他。
- 使用 JS:
db.out.find().forEach(function(doc) {db.target.insert(doc)})
- 使用 mongoexport / mongoimport
这不是有史以来最漂亮的东西,但作为另一种替代语法(来自 post-processing archive/append 操作)...
db.targetCollection.insertMany(db.runCommand(
{
aggregate: "sourceCollection",
pipeline:
[
{ $skip: 0 },
{ $limit: 5 },
{
$project:
{
myObject: "$$ROOT",
processedDate: { $add: [new ISODate(), 0] }
}
}
]
}).result)
我不确定这与 forEach 变体相比如何,但我发现它阅读起来更直观。
开始Mongo 4.2
,新的$merge
聚合运算符(类似于$out
)允许合并 聚合管道的结果到指定的集合:
鉴于此输入:
db.source.insert([
{ "_id": "id_1", "a": 34 },
{ "_id": "id_3", "a": 38 },
{ "_id": "id_4", "a": 54 }
])
db.target.insert([
{ "_id": "id_1", "a": 12 },
{ "_id": "id_2", "a": 54 }
])
$merge
聚合阶段可以这样使用:
db.source.aggregate([
// { $whatever aggregation stage, for this example, we just keep records as is }
{ $merge: { into: "target" } }
])
生产:
// > db.target.find()
{ "_id" : "id_1", "a" : 34 }
{ "_id" : "id_2", "a" : 54 }
{ "_id" : "id_3", "a" : 38 }
{ "_id" : "id_4", "a" : 54 }
请注意,$merge
运算符附带 many options 以指定如何合并与现有记录冲突的插入记录。
在这种情况下(使用默认选项),这:
保留目标集合的现有文档(
{ "_id": "id_2", "a": 54 }
就是这种情况)将聚合管道输出中的文档不存在时插入到目标集合中(基于
_id
- 这是{ "_id" : "id_3", "a" : 38 }
的情况)在聚合管道生成目标集合中存在的文档时替换目标集合的记录(基于
_id
- 这是{ "_id": "id_1", "a": 12 }
替换为[=的情况23=])