我试图通过预先添加单个字段来混合两个字段。我不想在哪里条件中指定字段Id,因为我正在处理360万个数据。我只是想为所有记录组合同一集合的两个字段 例如:我有一个集合
LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener
我需要输出就像所有记录的data2 = data1 + data2一样。
{
"_id": "56c58adf4f40",
"data1": "test1",
"data2": "test2"
}
我已经尝试过以下方法来插入一个字段但是当我提供id时只插入指定的数据:
{
"_id": "56c58adf4f40",
"data1": "test1",
"data2": "test1 test2"
}
答案 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
,该版本deprecated已Bulk()
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);