Chr*_*tow 331 mongodb mongodb-query aggregation-framework
在MongoDB中,是否可以使用另一个字段中的值更新字段的值?等效的SQL将是这样的:
UPDATE Person SET Name = FirstName + ' ' + LastName
Run Code Online (Sandbox Code Playgroud)
MongoDB伪代码将是:
db.person.update( {}, { $set : { name : firstName + ' ' + lastName } );
Run Code Online (Sandbox Code Playgroud)
Car*_*ona 234
你应该迭代.对于您的具体情况:
db.person.find().snapshot().forEach(
function (elem) {
db.person.update(
{
_id: elem._id
},
{
$set: {
name: elem.firstname + ' ' + elem.lastname
}
}
);
}
);
Run Code Online (Sandbox Code Playgroud)
sty*_*ane 191
执行此操作的最佳方法是使用聚合框架来计算新字段.
最有效的解决方案是在MongoDB 3.4中使用updateOne 和updateMany聚合管道运算符.
db.collection.<update method>(
{},
[
{"$set": {"name": { "$concat": ["$firstName", " ", "$lastName"]}}}
]
)
Run Code Online (Sandbox Code Playgroud)
请注意,这不会更新您的集合,而是替换现有集合或创建新集合.此外,对于需要"类型转换"的更新操作,您将需要客户端处理,并且根据操作,您可能需要使用update方法而不是$set方法.
我们这样做的方法是通过$addFields我们的文档并使用$set字符串聚合运算符来返回连接的字符串.然后,您可以从那里迭代光标并使用$addFields更新运算符使用批量操作将新字段添加到文档中,以实现最高效率.
db.collection.aggregate(
[
{ "$addFields": {
"name": { "$concat": [ "$firstName", " ", "$lastName" ] }
}},
{ "$out": "collection" }
]
)
Run Code Online (Sandbox Code Playgroud)
从这里,你需要使用该$out方法.
var cursor = db.collection.aggregate([
{ "$project": {
"name": { "$concat": [ "$firstName", " ", "$lastName" ] }
}}
])
Run Code Online (Sandbox Code Playgroud)
在此版本中,您需要使用现已弃用的find()API及其相关方法.
var requests = [];
cursor.forEach(document => {
requests.push( {
'updateOne': {
'filter': { '_id': document._id },
'update': { '$set': { 'name': document.name } }
}
});
if (requests.length === 500) {
//Execute per 500 operations and re-init
db.collection.bulkWrite(requests);
requests = [];
}
});
if(requests.length > 0) {
db.collection.bulkWrite(requests);
}
Run Code Online (Sandbox Code Playgroud)
var bulk = db.collection.initializeUnorderedBulkOp();
var count = 0;
cursor.snapshot().forEach(function(document) {
bulk.find({ '_id': document._id }).updateOne( {
'$set': { 'name': document.name }
});
count++;
if(count%500 === 0) {
// Excecute per 500 operations and re-init
bulk.execute();
bulk = db.collection.initializeUnorderedBulkOp();
}
})
// clean up queues
if(count > 0) {
bulk.execute();
}
Run Code Online (Sandbox Code Playgroud)
Nie*_*est 103
显然,自MongoDB 3.4以来,有一种方法可以有效地完成这项工作,请参阅styvane的回答.
下面的过时答案
您还不能在更新中引用文档本身.您需要遍历文档并使用函数更新每个文档.见这个答案的一个例子,或者这一个服务器端eval().
Eri*_*thi 42
对于具有高活动性的数据库,您可能会遇到更新影响主动更改记录的问题,因此我建议使用snapshot()
db.person.find().snapshot().forEach( function (hombre) {
hombre.name = hombre.firstName + ' ' + hombre.lastName;
db.person.save(hombre);
});
Run Code Online (Sandbox Code Playgroud)
http://docs.mongodb.org/manual/reference/method/cursor.snapshot/
Xav*_*hot 20
开始Mongo 4.2,db.collection.update()可以接受聚合管道,最后允许基于另一个字段更新/创建一个字段:
// { firstName: "Hello", lastName: "World" }
db.collection.update(
{},
[{ $set: { name: { $concat: [ "$firstName", " ", "$lastName" ] } } }],
{ multi: true }
)
// { "firstName" : "Hello", "lastName" : "World", "name" : "Hello World" }
Run Code Online (Sandbox Code Playgroud)
第一部分{}是匹配查询,过滤要更新的文档(在我们的例子中是所有文档)。
第二部分[{ $set: { name: { ... } }]是更新聚合管道(注意方括号表示使用聚合管道)。$set是一个新的聚合运算符,是 的别名$addFields。
不要忘记{ multi: true },否则只会更新第一个匹配的文档。
我尝试了上述解决方案,但我发现它不适合大量数据.然后我发现了流功能:
MongoClient.connect("...", function(err, db){
var c = db.collection('yourCollection');
var s = c.find({/* your query */}).stream();
s.on('data', function(doc){
c.update({_id: doc._id}, {$set: {name : doc.firstName + ' ' + doc.lastName}}, function(err, result) { /* result == true? */} }
});
s.on('end', function(){
// stream can end before all your updates do if you have a lot
})
})
Run Code Online (Sandbox Code Playgroud)
update()方法将聚合管道作为参数,例如
db.collection_name.update(
{
// Query
},
[
// Aggregation pipeline
{ "$set": { "id": "$_id" } }
],
{
// Options
"multi": true // false when a single doc has to be updated
}
)
Run Code Online (Sandbox Code Playgroud)
可以使用聚合管道使用现有值设置或取消设置该字段。
注意:$与字段名称一起使用来指定必须读取的字段。
关于此答案,根据此更新,快照功能在版本3.6中已弃用。因此,在3.6及更高版本上,可以通过以下方式执行操作:
db.person.find().forEach(
function (elem) {
db.person.update(
{
_id: elem._id
},
{
$set: {
name: elem.firstname + ' ' + elem.lastname
}
}
);
}
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
169111 次 |
| 最近记录: |