如何在mongo db collection的所有记录中添加字段?

时间:2016-02-18 12:26:26

标签: mongodb

我试图通过预先添加单个字段来混合两个字段。我不想在哪里条件中指定字段Id,因为我正在处理360万个数据。我只是想为所有记录组合同一集合的两个字段 例如:我有一个集合

LocationListener,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener

我需要输出就像所有记录的data2 = data1 + data2一样。

{
  "_id": "56c58adf4f40",
  "data1": "test1",
   "data2": "test2"

}

我已经尝试过以下方法来插入一个字段但是当我提供id时只插入指定的数据:

{
  "_id": "56c58adf4f40",
  "data1": "test1",
   "data2": "test1 test2"

}

1 个答案:

答案 0 :(得分:2)

在聚合框架管道的 $concat 步骤中使用 $project 运算符。运行以下聚合将为您提供所需的输出,而无需更新您的集合:

db.collection.aggregate([
    {
        "$project": {
            "data1": 1,
            "data2": { $concat: [ "$data1", " ", "$data2" ] }
        }
    }
])

如果您希望使用此结果集更新集合,则可以使用 forEach() 光标上的 aggregate() 方法进行迭代结果列表中的文档,使用循环内的每个文档更新您的集合。例如:

var cursor = db.collection.aggregate([
        {
            "$project": {
                "data1": 1,
                "data2": { $concat: [ "$data1", " ", "$data2" ] }
            }
        }
    ]),
    updateCollUsingAgg = function(doc){
        db.collection.update(
            { "_id": doc._id },
            { "$set": { "data2": doc.data2 } }
        )
    }

cursor.forEach(updateCollUsingAgg);

您也可以在不使用 aggregate() 方法的情况下更新集合,但使用 find() 光标来迭代您的集合:

var cursor = db.collection.find(),
    updateCollUsingFind = function(doc){
        db.collection.update(
            { "_id": doc._id },
            { "$set": { "data2": doc.data1+" "+doc.data2 } }
        )
    };
cursor.forEach(updateCollUsingFind);

为了提高性能,特别是在处理大型集合时,利用Bulk() API有效地批量更新集合,因为您将批量发送操作到服务器(例如,批量处理)大小500)。这样可以提供更好的性能,因为您不会将每个请求发送到服务器,而是每500个请求中只发送一次,从而使您的更新更加高效和快捷。

以下示例演示如何使用MongoDB版本>= 2.6 and < 3.2中提供的Bulk() API。

// Bulk update collection
var bulkUpdateOp = db.collection.initializeUnorderedBulkOp(), 
    pipeline = [
        {
            "$project": {
                "data1": 1,
                "data2": { $concat: [ "$data1", " ", "$data2" ] }
            }
        }
    ],
    counter =  0, // counter to keep track of the batch update size
    // Get modified data2 fields using aggregation framework
    cursor = db.collection.aggregate(pipeline); 

cursor.forEach(function(doc){
    // update collection
    bulkUpdateOp.find({"_id": doc._id}).updateOne({ "$set": { "data2": doc.data2 } }); 
    counter++; // increment counter
    // execute the bulk update operation in batches of 500
    if (counter % 500 == 0) { 
        bulkUpdateOp.execute();
        bulkUpdateOp = db.collection.initializeUnorderedBulkOp();
    }
});

if (counter % 500 != 0) { bulkUpdateOp.execute(); }

下一个示例适用于新的MongoDB版本3.2,该版本deprecatedBulk() bulkWrite(),并使用map()提供了一套更新的apis。

它使用与上面相同的游标,但不是迭代结果,而是使用其{{3}}方法创建具有批量操作的数组:

 var pipeline = [
        {
            "$project": {
                "data1": 1,
                "data2": { $concat: [ "$data1", " ", "$data2" ] }
            }
        }
    ],
    cursor = db.collection.aggregate(pipeline),
    bulkUpdateOps = cursor.map(function (doc) { 
        return { 
            "updateOne": {
                "filter": { "_id": doc._id },
                "update": { "$set": { "data2": doc.data2 } } 
             }
        };
    });         

db.collection.bulkWrite(bulkUpdateOps);