在MongoDB文档中向嵌套数组添加属性

6
我有一个MongoDB文档,其结构如下:
> db.user.find().limit(1);
{ "_id" : "1", "foo" : { "bars" : [
    {
        "name" : "bar1"
    },
    {
        "name" : "bar2"
    },
], ... }, ... }

我想给每个bar添加一个新属性。我已经让我的脚本在bars数组上进行迭代,但我无法将新属性加入其中,我该怎么做?

var users = db.user.find({"foo.bars":{$exists:true}});

users.forEach(function(user) {
    user.foo.bars.forEach(function(bar)
    {
       printjson(bar);
       //how can I specify the current 'bar' in this update?
       //db.experience.update({_id: user._id}, {$set: {"what goes here?" : "newbarValue"}});
    });
});

你确定要给每个条形图添加一个新属性吗?特别是在{"user.foo.bars.${bar}中,你想要做什么?'${bar}'应该怎么用?难道你试图发明新的语法而没有检查事物实际上是如何工作的吗? - user2665694
"user.foo.bars.${bar}" 是表示性的 - 它不是有效的语法,你会注意到它被注释掉了。我试图表达我的意图。 - markdsievers
3个回答

10

所以传教的人说:

var users = db.user.find({"foo.bars":{$exists:true}});

users.forEach(function(user) {
    var id = user._id;

    var foo_bars = user.foo.bars;
    var new_foo_bars = [];

    for(var i = 0; i < foo_bars.length; i++) {
        var foo_bar = foo_bars[i];
        foo_bar['newkey'] = 'newvalue';
        new_foo_bars.push(foo_bar);
    }

    db.user.update({"_id":id}, {$set:{"foo.bars":new_foo_bars}});
});

2
据我所知,使用forEach不具有良好的可扩展性,它会在更新运行期间锁定整个数据库。 - Johann Philipp Strathausen
很好的答案,但有没有避免使用foreach的方法?我正在使用上述方法从另一个集合中检索变量并将其添加到集合的结果集中,然后再呈现模板。在SQL中,我会通过ID进行连接,MongoDB中是否有类似的方法? - Thordin9

1

我注意到你在JS中在客户端滚动数组。

如果你从旧的数组中形成一个新的“bars”数组,然后将其作为一个全新的值推入,这意味着你只需要进行一次DB调用,代码非常优雅。

如果MongoDB通常不支持它,最好在客户端上完成工作。


正确 - 您可以通过$set在一个数组元素下添加单个项目,而不是全部添加。因此,请在客户端执行此操作。您可以通过localhost在服务器上运行客户端脚本,然后它应该表现得非常好。 - dm.

0
您必须逐个更新嵌套文档的每个元素。使用位置操作符“$”将无法工作,因为它只能在第一次匹配时起作用(如所述)。

这里有什么是无用的?你只能这样做。 - user2665694
你必须单独更新嵌套文档的每个元素。这本质上就是我问如何做到这一点 - 将其重新陈述为答案是没有用的。指向相关文档或提供一行伪代码将是很好的。在来这里之前,我花了一个小时试图解决这个问题 - 所以我很失望它被投票下降,并建议我还没有尝试过使用文档进行自我解决。 - markdsievers
1
你可以在数组$set操作中使用硬索引。因此,db.user.update({_id: user._id}, {$set: {'foo.bars.0.someValue' : "newbarValue"}})是有效的。你只需要用一个计数器替换0,并在内部for循环中递增即可解决你的问题。如果我理解你的问题正确的话。 - Remon van Vliet
@Remon。谢谢,这是一个好建议。如果我在那里硬编码一个索引,就像你说的那样,它确实可以工作,但是当我尝试在该字符串中使用变量索引或提取构建“foo.bars。”+ i +“。someValue”的变量并在update(...)函数中使用该变量时,似乎无法使update(...)函数工作。 - markdsievers
是的,在JS中你不能这样做(至少我也不知道如何做,不是专家)。但我认为这只是在shell或者使用node时的问题。大多数其他编程语言都可以很好地完成这个任务。 - Remon van Vliet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接