【问题标题】:How can I update a single child document in a MongoDB document array using something like $set and $elemMatch?如何使用 $set 和 $elemMatch 更新 MongoDB 文档数组中的单个子文档?
【发布时间】:2014-04-06 20:42:52
【问题描述】:

我有一个这样的集合结构:

albums: {
    2oBkjqYFwf3vrgDj4: {
        _id: "2oBkjqYFwf3vrgDj4",
        titles: [
            {
                titleText: "i am an album"
            },
            {
                titleText: "this is my other title"
            }
        ]
    }
}

我想做类似下面的事情来更新 titleText 等于什么的地方,然后改变它:

db.albums.update({"_id": "2oBkjqYFwf3vrgDj4", "titles": {$elemMatch: {"titleText": "i am an album"}}},
    {$set: {
        "titles.titleText": "i am not an album"
    }
)

我知道我可以做一个 foreach,但这似乎浪费了很多资源,因为我计划在 titles.titleText 上建立一个索引。

是我遗漏了什么,还是没有简单的方法可以做到这一点? 我正在使用 Meteor,但如果 MongoDB 有办法做到这一点,我认为它不应该改变任何逻辑。

谢谢大家!

【问题讨论】:

标签: mongodb meteor mongodb-query


【解决方案1】:

原来我的问题是link的转贴

这个问题在MongoDB中可以通过做来解决,

db.albums.update({
        "_id": "2oBkjqYFwf3vrgDj4",
        "titles.titleText": "i am an album"
    },
    {$set:
        {"titles.$.titleText": "i am not an album"}
    }
)

上一个问题发布时,位置运算符wasn't supported by minimongo。到目前为止,对于security reasons,mongo 选择器不能在客户端代码中使用。

上面的方法必须从服务器上的 Meteor.method() 调用。

【讨论】:

    【解决方案2】:

    使用流星收集 api,您可以使用 updatedocumentation here。您提供一个选择器,然后提供一个修饰符。你也可以直接用 mongo 做同样的事情。一般语法如下,但我自己没有运行它。我不知道是否存在类似于您的代码的更奇特的方式,它可能是 DRY'er,但应该可以完成工作。

    Albums.update(
        {_id: "2oBkjqYFwf3vrgDj4", "titles.titleText": "i am an album"},
        {$set:{"titles.titleText": "i am not an album"}}
    };
    

    【讨论】:

    • 它可以工作,但您需要知道索引才能使$set 工作。所以我必须做{$set:{"titles.0.titleText": "i am not an album"}},但这意味着我必须先获取索引,然后才能继续更新它。希望有人知道更简单的方法。
    • 我认为您要么需要一些 js 来查找索引,要么需要以不同的方式构建数据库:有一个专辑集合和一个标题集合。如果需要,让一个引用另一个的 id 和 ensureIndex() 以进行快速交叉引用。我怀疑这是你会选择采用的解决方案,但我认为这是唯一一个在没有额外 js 的情况下给定参数的解决方案。您必须考虑执行此操作的频率以及需要多长时间。不过,我很高兴被证明是错误的!
    • 是的,我知道有人会建议重组,但这绝对是我构建查询结构的最快方式。我会以我不需要的方式进行规范化,仅仅是因为没有简单的方法来更新子文档。
    • 如果顺序无关紧要,您可以使用 $pull 和 $push。 docs.mongodb.org/manual/reference/operator/update-array
    • 其实看起来是这样的:docs.mongodb.org/manual/reference/operator/update/positional/…checkout 最后一个例子。
    【解决方案3】:

    $set 在客户端不能很好地工作。一个很好的解决方法是(在派对中找到他的)示例。

    step 1: get the array for your items.
        var album = albums.findOne().services;
    step 2: lets find the index we want using _indexOf and _pluck
                     var indexToUpdate = _.indexOf(_.pluck('insert your array', 'insert your column name'), 'insert the one you want to update');
    
                    var modifier = { $set: {} };
                    modifier.$set["services." + indexToUpdate + ".youfieldinarray"] = 'your new value'.
    step 3: update your item object      
    albumns.update(Business.findOne()._id, modifier);
    

    不确定我是否会在大量收藏中这样做,但对于较小的客户端,它运作良好。

    【讨论】:

      猜你喜欢
      • 2019-05-25
      • 1970-01-01
      • 2016-11-04
      • 2013-09-18
      • 1970-01-01
      • 2013-09-03
      • 2016-11-23
      • 1970-01-01
      • 2016-12-31
      相关资源
      最近更新 更多