使用另一个字段的值更新 MongoDB 字段 [英] Update MongoDB field using value of another field
问题描述
在 MongoDB 中,是否可以使用来自另一个字段的值来更新字段的值?等效的 SQL 将类似于:
In MongoDB, is it possible to update the value of a field using the value from another field? The equivalent SQL would be something like:
UPDATE Person SET Name = FirstName + ' ' + LastName
MongoDB 伪代码为:
And the MongoDB pseudo-code would be:
db.person.update( {}, { $set : { name : firstName + ' ' + lastName } );
推荐答案
最好的方法是在 4.2+ 版本中,它允许在 update 文档和 中使用聚合管道="https://docs.mongodb.com/master/reference/method/db.collection.updateOne/#update-with-aggregation-pipeline" rel="nofollow noreferrer">updateOne
, updateMany
或 update
收集方法.请注意,后者在大多数语言驱动程序中已被弃用.
The best way to do this is in version 4.2+ which allows using of aggregation pipeline in the update document and the updateOne
, updateMany
or update
collection methods. Note that the latter has been deprecated in most if not all languages drivers.
4.2 版还引入了 $set
管道阶段运算符,它是 $addFields 的别名
.我将在这里使用 $set
,因为它映射我们正在努力实现的目标.
Version 4.2 also introduced the $set
pipeline stage operator which is an alias for $addFields
. I will use $set
here as it maps with what we are trying to achieve.
db.collection.<update method>(
{},
[
{"$set": {"name": { "$concat": ["$firstName", " ", "$lastName"]}}}
]
)
请注意,该方法的第二个参数中的方括号定义了聚合管道而不是普通的更新文档.使用普通文档将无法正常工作.
Note that square brackets in the second argument to the method which defines an aggregation pipeline instead of a plain update document. Using a plain document will not work correctly.
在 3.4+ 中,您可以使用 $addFields
和 $out
聚合管道运算符.
In 3.4+ you can use $addFields
and the $out
aggregation pipeline operators.
db.collection.aggregate(
[
{ "$addFields": {
"name": { "$concat": [ "$firstName", " ", "$lastName" ] }
}},
{ "$out": "collection" }
]
)
请注意,这不会更新您的集合,而是替换现有集合或创建一个新集合.也适用于需要类型转换"的更新操作您将需要客户端处理, 并且根据操作,您可能需要使用 find()
方法而不是 .aggreate()
方法.
Note that this does not update your collection but instead replaces the existing collection or creates a new one. Also for update operations that require "typecasting" you will need client-side processing, and depending on the operation, you may need to use the find()
method instead of the .aggreate()
method.
我们这样做的方式是通过 $project
我们的文档并使用 $concat
字符串聚合运算符返回连接的字符串.从那里,您然后迭代 cursor 并使用 $set
更新操作符,使用批量操作将新字段添加到您的文档中,以实现最高效率.
The way we do this is by $project
ing our documents and using the $concat
string aggregation operator to return the concatenated string.
From there, you then iterate the cursor and use the $set
update operator to add the new field to your documents using bulk operations for maximum efficiency.
var cursor = db.collection.aggregate([
{ "$project": {
"name": { "$concat": [ "$firstName", " ", "$lastName" ] }
}}
])
MongoDB 3.2 或更新版本
由此,您需要使用bulkWrite
方法.
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);
}
MongoDB 2.6 和 3.0
从这个版本开始,你需要使用现已弃用的批量
API 及其相关方法.
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();
}
MongoDB 2.4
cursor["result"].forEach(function(document) {
db.collection.update(
{ "_id": document._id },
{ "$set": { "name": document.name } }
);
})
这篇关于使用另一个字段的值更新 MongoDB 字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!