问题
I have thousands of documents in this format:
{
"_id" : ObjectId("51e98d196b01c2085c72d731"),
"messages" : [
{
"_id" : ObjectId("520167056b01c20bb9eee987"),
"id" : ObjectId("520167056b01c20bb9eee987"),
},
{
"_id" : ObjectId("520167056b01c20bb9eee988"),
"id" : ObjectId("520167056b01c20bb9eee988"),
},
{
"_id" : ObjectId("520167056b01c20bb9eee989"),
"id" : ObjectId("520167056b01c20bb9eee989"),
}
],
}
I need to remove the duplicate "id" field. This is what I have tried:
db.forum_threads.update({}, {$unset: {"messages.$.id": 1}}, {multi: true});
This is the error I am getting:
Cannot apply the positional operator without a corresponding query field containing an array.
回答1:
The reason you're getting that error is because you don't have any predicate in the filter clause. You can do this:
mongos> db.test.update({"messages.id": {$exists: true}}, {$unset: {"messages.$.id":true}}, {multi:true})
And you won't get an error - in fact one of the documents will have the id
attribute removed. The problem is that the positional operator only matches the FIRST element of the array that matches your predicate, it doesn't match all elements. The bigger issue is that it's not currently possible to update all the elements in an array in MongoDB (https://jira.mongodb.org/browse/SERVER-1243).
You'll either need to iterate through each element in the array using the numerical position ("messages.0.id", "messages.1.id", etc.) or you can pull the array into your application, loop through the elements and update them, and then save the array back out.
You can see from the JIRA ticket that this issue has been open for quite awhile but 10gen doesn't seem to consider it very high priority.
回答2:
With Mongo 3.6 you can use the new positional identifier and do something like:
db.test.update({"messages.id": {$exists: true}}, {$unset: {"messages.$[].id":true}}, {multi:true})
来源:https://stackoverflow.com/questions/18409120/mongodb-removing-a-field-from-all-subdocuments-in-an-array-field