Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB: Removing a field from ALL subdocuments in an array field

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.
like image 647
user1236803 Avatar asked Aug 23 '13 18:08

user1236803


People also ask

How do I remove an element from an array in MongoDB?

To remove an element, update, and use $pull in MongoDB. The $pull operator removes from an existing array all instances of a value or values that match a specified condition.

How do I delete a nested field in MongoDB?

To remove an element from a doubly-nested array in MongoDB document, you can use $pull operator. Now field "UserZipCode": "20010" has been removed from a doubly-nested array.

How do you update an array element in MongoDB?

You can use the updateOne() or updateMany() methods to add, update, or remove array elements based on the specified criteria. It is recommended to use the updateMany() method to update multiple arrays in a collection.

How to remove a field completely from a MongoDB document?

How to remove a field completely from a MongoDB document? You can use $unset operator to remove a field completely from a MongoDb document. The syntax is as follows:

Is it possible to remove a value from a subdocument?

Actually it will remove the value, BUT only from the first occurrence of the subdocument, because of the way positional operator works: You also can not use $unset (as you tried before) because it can not work on arrays (and are you basically trying to remove a key from a document from the array).

How to count the longest array in a MongoDB object?

Also, to count the longest array in a mongodb object, an aggregate can be done, something like this: Just want to emphasize that this is not a pretty solution but is way faster than fetching and saving. Not the answer you're looking for?


1 Answers

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.

like image 131
Mason Avatar answered Sep 20 '22 10:09

Mason