【问题标题】:How do I append Mongo DB aggregation results to an existing collection?如何将 Mongo DB 聚合结果附加到现有集合?
【发布时间】:2015-04-28 18:30:39
【问题描述】:

我正在尝试使用以下代码对现有的 Mongo DB 集合执行多次插入

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 都会删除以前的文档并插入新的结果。

你能帮帮我吗?

【问题讨论】:

标签: mongodb aggregation-framework


【解决方案1】:

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 } 替换为{ "_id" : "id_1", "a" : 34 } 的情况)

    李>

【讨论】:

【解决方案2】:

简短的回答是“你不能”:

如果 $out 操作指定的集合已经存在,那么在聚合完成后,$out 阶段会自动将现有集合替换为新的结果集合。 $out 操作不会更改先前集合中存在的任何索引。如果聚合失败,$out 操作不会更改预先存在的集合。

作为一种解决方法,您可以在聚合之后将$out 指定的集合文档复制到“永久”集合中,方法有以下几种(但其中一种都不是理想的):

  • copyTo() 是最简单的,请注意警告。不要为了小的结果而使用其他。
  • 使用JS:db.out.find().forEach(function(doc) {db.target.insert(doc)})
  • 使用 mongoexport / mongoimport

【讨论】:

  • 不敢相信他们没有办法追加。这是一个拥有数百万资金的数据库?可怜。
  • Ori,你的答案看起来不错。可能你想编辑它并添加这个选项stackoverflow.com/a/37433640/2834978。 db.col1.insert(db.col2.aggregate(...).toArray())
【解决方案3】:

这不是最漂亮的东西,而是另一种替代语法(来自后处理归档/追加操作)...

db.targetCollection.insertMany(db.runCommand(
{
    aggregate: "sourceCollection",
    pipeline: 
    [
        { $skip: 0 },
        { $limit: 5 },
        { 
            $project:
            {
                myObject: "$$ROOT",
                processedDate: { $add: [new ISODate(), 0] }
            }
        }
    ]
}).result)

我不确定这与 forEach 变体的对比如何,但我发现它更易于阅读。

【讨论】:

    猜你喜欢
    • 2014-02-19
    • 1970-01-01
    • 2014-01-25
    • 1970-01-01
    • 1970-01-01
    • 2015-04-25
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多