MongoDB聚合框架不保留使用$addFields添加的内容

d7v8vwbk  于 2023-11-17  发布在  Go
关注(0)|答案(5)|浏览(168)

字段被添加,但随后消失。下面是mongo shell中的代码:

> db.users.aggregate([{$addFields:{totalAge:{$sum:"$age"}}}])
{ "_id" : ObjectId("5acb81b53306361018814849"), "name" : "A", "age" : 1, "totalAge" : 1 }
{ "_id" : ObjectId("5acb81b5330636101881484a"), "name" : "B", "age" : 2, "totalAge" : 2 }
{ "_id" : ObjectId("5acb81b5330636101881484b"), "name" : "C", "age" : 3, "totalAge" : 3 }
> db.users.find().pretty()
{ "_id" : ObjectId("5acb81b53306361018814849"), "name" : "A", "age" : 1 }
{ "_id" : ObjectId("5acb81b5330636101881484a"), "name" : "B", "age" : 2 }
{ "_id" : ObjectId("5acb81b5330636101881484b"), "name" : "C", "age" : 3 }

字符串

idv4meu8

idv4meu81#

聚合只从集合中读取数据;它不会编辑集合。考虑聚合的最佳方式是读取一些数据并操作它以供立即使用。
如果你想在主源代码中更改它,那么你必须使用update方法。
或者更简单的方法(不是最好的,但很容易)

db.users.aggregate([{$addFields:{totalAge:{$sum:"$age"}}}]).forEach(function (x){
    db.users.save(x)
})

字符串

2lpgd968

2lpgd9682#

Nozar的回答 * 是 * 正确的,但是**.保存()现在被弃用了。
使用**.updateOne和$set**修改答案,而不是使用他/她的确切答案。
老/过时的答案:

db.users
    .aggregate([{$addFields:{totalAge:{$sum:"$age"}}}])
    .forEach(function (x){db.users.save(x)})

字符串
新/工作答案:

db.users
    .aggregate([{$addFields:{totalAge:{$sum:"$age"}}}])
    .forEach(function (x){db.users.updateOne({name: x.name}, {$set: {totalAge: x.totalAge}})})

  • 注意事项:在我的示例中,我使用'name'来过滤(在本例中,本质上是匹配)'users'集合中的文档,但您可以使用任何唯一字段(例如_id字段)。

Nozar让我找到了我提供的更新的答案,因为我刚刚在我的项目中使用了它!(在我的项目中,我在$addFields管道阶段之前使用了$match管道阶段,因为我只是想对我的集合中的单个文档进行此操作,而不是所有文档)

hivapdat

hivapdat3#

聚合管道不会改变原始数据;它所做的是获取数据的临时内存副本,并对其执行一系列操作(仍然在内存中),然后将其发送到客户端。
这类似于db.collection.find().sort()的排序方式;排序只改变返回给客户端的内容,而不改变存储在数据库中的内容。
唯一的 * 例外 * 是当你使用$out stage时,它将聚合的结果保存到另一个集合中。你可以看到,因为他们必须添加一个特殊类型的阶段来完成这一点,所以普通的聚合不会写回存储的数据。

llmtgqce

llmtgqce4#

原因是,你的方法完全不同。在聚合中,你在那个查询中使用了**$addFields**,你会得到一个totalAge。但是根据你的查找查询,你可以得到你存储在数据库中的特定数据。这里你没有计算totalAge
希望你能理解。

s71maibg

s71maibg5#

您可以使用$merge,例如:

> db.users.aggregate([{$addFields:{totalAge:{$sum:"$age"}}},{merge: "users"}])

字符串

相关问题