【问题标题】:Memory effective way to transform collection in mongodb在mongodb中转换集合的内存有效方法
【发布时间】:2016-04-30 23:46:30
【问题描述】:

我在 mongodb 中有这样的集合:

{
        "_id" : ObjectId("56a5f47ed420cf0db5b70242"),
        "tag" : "swift",
        "values" : [
                {
                        "word" : "osx",
                        "value" : 0.02
                },
                {
                        "word" : "compiler",
                        "value" : 0.01
                }
        ]
},
{
        "_id" : ObjectId("56a5f47ed420cf0db5b70243"),
        "tag" : "c++",
        "values" : [
                {
                        "word" : "namespace",
                        "value" : 0.04
                },
                {
                        "word" : "compiler",
                        "value" : 0.05
                }
        ]
}

我需要像这样在集合中转换它:

{
        "_id" : ObjectId("56a5f4e5d420cf0db5b70247"),
        "word" : "namespace",
        "values" : [
                {
                        "tag" : "c++",
                        "value" : 0.04
                }
        ]
},
{
        "_id" : ObjectId("56a5f4e5d420cf0db5b70248"),
        "word" : "compiler",
        "values" : [
                {
                        "tag" : "swift",
                        "value" : 0.01
                },
                {
                        "tag" : "c++",
                        "value" : 0.05
                }
        ]
},
{
        "_id" : ObjectId("56a5f4e5d420cf0db5b70249"),
        "word" : "osx",
        "values" : [
                {
                        "tag" : "swift",
                        "value" : 0.02
                }
        ]
}

我是使用 mongodb 和 MapReduce 的新手,有一些问题:

  1. 在我的情况下,我应该使用 MapReduce 或 Aggregation 框架和 $out 到另一个集合吗?
  2. 哪种方法对内存更有效?因为集合很大 (3gb),而我只有 8gb 的 RAM,所以我担心会出现 OutOfMemory 错误。
  3. 如果我将使用 MapReduce,map 和 reduce 阶段应该是什么?我应该在地图阶段发出{"word": word, "values": {"tag":tag, "value": value} } 之类的项目并将其合并到reduce 状态?

【问题讨论】:

    标签: mongodb mapreduce mongodb-query aggregation-framework


    【解决方案1】:

    使用.aggregate() 方法。

    您需要使用$unwind 运算符对“值”数组进行非规范化。管道的最后一个阶段是 $group 阶段,您可以在其中按“values.word”对文档进行分组,并使用 $push 累加器运算符返回每个组的子文档数组。

    从那里,您可以使用 "bulk" 操作将您的文档插入到新集合中。

    var bulk = db.myCollection.initializeOrderedBulkOp();
    var count  = 0;
    db.collection.aggregate( [ 
        { "$unwind": "$values" }, 
        { "$group": { 
            "_id": "$values.word", 
            "values": { 
                 "$push": { "tag": "$tag", "value": "$values.value" } 
            } 
        } }
    ]).forEach(function(doc) { 
        bulk.insert( { "word": doc._id, "values": doc.values } );
        count++;
        if ( count % 1000 === 0 ) {
            // Execute per 1000 operations and re-init
            bulk.execute();
            bulk = db.myCollection.initializeOrderedBulkOp();
        }
    });
    // Clean up queues
    if (count > 0 ) {
        bulk.execute();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-08
      相关资源
      最近更新 更多