我有数千份这种格式的文档:
{
"_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.
您收到该错误的原因是过滤子句中没有任何谓词。你可以这样做:
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 票证中可以看到这个问题已经开放了很长一段时间,但 10gen 似乎并不认为它具有很高的优先级。
使用 Mongo 3.6,您可以使用新的 位置标识符 并执行以下操作:
db.test.update({"messages.id": {$exists: true}}, {$unset: {"messages.$[].id":true}}, {multi:true})
这似乎对我很有效(2023)。请注意,mongoDB 可能会因某些文档中缺少的数组而出错,因此出现这种情况。
db.test.updateMany(
{ messages: { $exists: true } },
{ $unset: { "messages.$[].id": "" } }
)