使用另一个字段的值更新 MongoDB 字段
在 MongoDB 中,是否可以使用另一个字段的值来更新一个字段的值?等效的 SQL 类似于:
UPDATE Person SET Name = FirstName + ' ' + LastName
MongoDB 伪代码如下:
db.person.update( {}, { $set : { name : firstName + ' ' + lastName } );
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
And the MongoDB pseudo-code would be:
db.person.update( {}, { $set : { name : firstName + ' ' + lastName } );
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
执行此操作的最佳方法是在版本 4.2+ 中,它允许在更新文档和
updateOne
,updateMany
或update
(已弃用大多数(如果不是全部)语言驱动程序)收集方法。MongoDB 4.2+
版本 4.2 还引入了
$set
< /a> 管道阶段运算符,它是$addFields< 的别名/代码>
。我将在这里使用
$set
,因为它映射我们想要实现的目标。请注意,该方法第二个参数中的方括号指定聚合管道而不是普通更新文档,因为使用简单文档将无法正常工作。
MongoDB 3.4+
在 3.4+ 中,您可以使用
$addFields
和$out
聚合管道运算符。请注意,这不会更新您的集合,而是替换现有集合或创建一个新集合。此外,对于需要“类型转换”的更新操作,您将需要 client-侧面处理,并且根据操作的不同,您可能需要使用
find()
方法而不是.aggreate()
方法。MongoDB 3.2 和 3.0
我们这样做的方式是通过
$project
我们的文档并使用
$concat< /code>
字符串聚合运算符返回连接的字符串。
然后,您迭代光标并使用
$set
更新运算符,使用批量操作将新字段添加到文档中,以实现最高效率。聚合查询:
MongoDB 3.2 或更高版本
您需要使用
bulkWrite
方法。MongoDB 2.6 和 3.0
从这个版本开始,您需要使用现已弃用的
Bulk
API 及其关联方法 。MongoDB 2.4
The best way to do this is in version 4.2+ which allows using the aggregation pipeline in the update document and the
updateOne
,updateMany
, orupdate
(deprecated in most if not all languages drivers) collection methods.MongoDB 4.2+
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.Note that square brackets in the second argument to the method specify an aggregation pipeline instead of a plain update document because using a simple document will not work correctly.
MongoDB 3.4+
In 3.4+, you can use
$addFields
and the$out
aggregation pipeline operators.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.MongoDB 3.2 and 3.0
The way we do this is by
$project
ing our documents and using the$concat
string aggregation operator to return the concatenated string.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.Aggregation query:
MongoDB 3.2 or newer
You need to use the
bulkWrite
method.MongoDB 2.6 and 3.0
From this version, you need to use the now deprecated
Bulk
API and its associated methods.MongoDB 2.4
你应该迭代一遍。对于您的具体情况:
You should iterate through. For your specific case:
显然,自 MongoDB 3.4 以来,有一种方法可以有效地做到这一点,请参阅 styvane 的答案。
下面的答案已过时
您无法在更新中引用文档本身(目前)。您需要迭代文档并使用函数更新每个文档。有关示例,请参阅此答案 ,或这个用于服务器端
eval()
。Apparently there is a way to do this efficiently since MongoDB 3.4, see styvane's answer.
Obsolete answer below
You cannot refer to the document itself in an update (yet). You'll need to iterate through the documents and update each document using a function. See this answer for an example, or this one for server-side
eval()
.对于活动频繁的数据库,您可能会遇到更新影响主动更改记录的问题,因此我建议使用 snapshot()
http://docs.mongodb.org/manual/reference/method/cursor.snapshot/
For a database with high activity, you may run into issues where your updates affect actively changing records and for this reason I recommend using snapshot()
http://docs.mongodb.org/manual/reference/method/cursor.snapshot/
从
Mongo 4.2
开始,db.collection.update()
可以接受聚合管道,最终允许基于另一个字段更新/创建一个字段:第一部分
{}
是匹配查询,过滤要更新的文档(在我们的例子中是所有文档)。第二部分
[{ $set: { name: { ... } }]
是更新聚合管道(注意方括号表示聚合管道的使用)。$set
是新的聚合运算符和$addFields
的别名。Starting
Mongo 4.2
,db.collection.update()
can accept an aggregation pipeline, finally allowing the update/creation of a field based on another field:The first part
{}
is the match query, filtering which documents to update (in our case all documents).The second part
[{ $set: { name: { ... } }]
is the update aggregation pipeline (note the squared brackets signifying the use of an aggregation pipeline).$set
is a new aggregation operator and an alias of$addFields
.关于此答案,根据此更新。所以,在3.6及以上版本,可以这样执行操作:
Regarding this answer, the snapshot function is deprecated in version 3.6, according to this update. So, on version 3.6 and above, it is possible to perform the operation this way:
update()
方法将聚合管道作为参数,例如可以使用聚合管道使用现有值设置或取消设置字段。
注意:使用
$
和字段名来指定要读取的字段。update()
method takes aggregation pipeline as parameter likeThe field can be set or unset with existing values using the aggregation pipeline.
Note: use
$
with field name to specify the field which has to be read.我尝试了上述解决方案,但发现它不适合大量数据。然后我发现了流功能:
I tried the above solution but I found it unsuitable for large amounts of data. I then discovered the stream feature:
以下是我们为将大约 150_000 条记录从一个字段复制到另一个字段而提出的方案。花费了大约 6 分钟,但与实例化和迭代相同数量的 ruby 对象相比,资源密集程度仍然要低得多。
Here's what we came up with for copying one field to another for ~150_000 records. It took about 6 minutes, but is still significantly less resource intensive than it would have been to instantiate and iterate over the same number of ruby objects.
使用 MongoDB 版本 4.2+,更新更加灵活,因为它允许在
update
、updateOne
和updateMany< 中使用聚合管道/代码>。您现在可以使用聚合运算符转换文档,然后进行更新,而无需明确声明
$set
命令(我们使用$replaceRoot: {newRoot: "$$ROOT"})
这里我们使用聚合查询从MongoDB的ObjectID“_id”字段中提取时间戳并更新文档(我不是SQL专家,但我认为SQL不提供任何自动生成的带有时间戳的ObjectID,你必须自动创建该日期)
With MongoDB version 4.2+, updates are more flexible as it allows the use of aggregation pipeline in its
update
,updateOne
andupdateMany
. You can now transform your documents using the aggregation operators then update without the need to explicity state the$set
command (instead we use$replaceRoot: {newRoot: "$$ROOT"}
)Here we use the aggregate query to extract the timestamp from MongoDB's ObjectID "_id" field and update the documents (I am not an expert in SQL but I think SQL does not provide any auto generated ObjectID that has timestamp to it, you would have to automatically create that date)
(我本想将此作为评论发布,但不能)
对于任何登陆此处尝试使用 c# 驱动程序使用文档中的另一个字段来更新一个字段的人...
我无法弄清楚如何使用任何
UpdateXXX
方法及其关联的重载,因为它们采用UpdateDefinition
作为参数。作为解决方法,我发现您可以在
IMongoDatabase
上使用RunCommand
方法(https://docs.mongodb.com/manual/reference/command/update/#dbcmd.update)。(I would have posted this as a comment, but couldn't)
For anyone who lands here trying to update one field using another in the document with the c# driver...
I could not figure out how to use any of the
UpdateXXX
methods and their associated overloads since they take anUpdateDefinition
as an argument.As a workaround, I found that you can use the
RunCommand
method on anIMongoDatabase
(https://docs.mongodb.com/manual/reference/command/update/#dbcmd.update).MongoDB 4.2+ Go 语言
MongoDB 4.2+ Golang