【问题标题】:MongoDB: Removing a field from ALL subdocuments in an array fieldMongoDB:从数组字段中的所有子文档中删除一个字段
【发布时间】:2013-08-26 21:02:00
【问题描述】:

我有成千上万的这种格式的文档:

{
"_id" : ObjectId("51e98d196b01c2085c72d731"),
"messages" : [
    {
        "_id" : ObjectId("520167056b01c20bb9eee987"),
        "id" : ObjectId("520167056b01c20bb9eee987"),

    },
    {
        "_id" : ObjectId("520167056b01c20bb9eee988"),
        "id" : ObjectId("520167056b01c20bb9eee988"),

    },
    {
        "_id" : ObjectId("520167056b01c20bb9eee989"),
        "id" : ObjectId("520167056b01c20bb9eee989"),
    }
],
}

我需要删除重复的“id”字段。这是我尝试过的:

db.forum_threads.update({}, {$unset: {"messages.$.id": 1}}, {multi: true});

这是我得到的错误:

Cannot apply the positional operator without a corresponding query field containing an array.

【问题讨论】:

    标签: mongodb pymongo mongoengine


    【解决方案1】:

    您收到该错误的原因是您在过滤子句中没有任何谓词。你可以这样做:

    mongos> db.test.update({"messages.id": {$exists: true}}, {$unset: {"messages.$.id":true}}, {multi:true})
    

    而且您不会收到错误消息 - 实际上其中一个文档将删除 id 属性。问题是位置运算符仅匹配与谓词匹配的数组的第一个元素,它不匹配所有元素。更大的问题是目前无法在 MongoDB (https://jira.mongodb.org/browse/SERVER-1243) 中更新数组中的所有元素。

    您需要使用数字位置(“messages.0.id”、“messages.1.id”等)遍历数组中的每个元素,或者您可以将数组拉入您的应用程序,循环遍历元素并更新它们,然后将数组保存回来。

    您可以从 JIRA 票证中看到,这个 issue 已经开放了很长一段时间,但 10gen 似乎并不认为它的优先级很高。

    【讨论】:

    • 我有预感这是不可能的。我想我必须走另一条路,谢谢!
    • 感谢您的解释,我错过了“.$”。在 $unset 子句中。它仅从遇到的第一个子文档中删除属性是出乎意料的行为,但这仍然有帮助,我只是运行了多次,直到将它们全部删除。
    【解决方案2】:

    使用 Mongo 3.6,您可以使用新的 positional identifier 并执行以下操作:

    db.test.update({"messages.id": {$exists: true}}, {$unset: {"messages.$[].id":true}}, {multi:true})
    

    【讨论】:

      猜你喜欢
      • 2013-07-07
      • 1970-01-01
      • 2020-11-21
      • 1970-01-01
      • 1970-01-01
      • 2013-11-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多