2

I have a problem with which I am struggling for quite some time.Suppose my document is like this

{"owner":"princu7", "books":[{"name":"the alchemist"},  {"name":"the alchemist"}, {"name":"the alchemist"}].

Now what do I do if I have to just remove one single element from the books array based on the matching of the name?I did it like this

var bookName="the alchemist";
var obj={"name":bookName}
db.collection("colName").update({"owner":"princu7"}, {$pull:{books:obj}}, {multi:false})

But the problems is that it removes all the entries in the array which have the name matching to "the alchemist". What I wanted was this

{"owner":"princu7", "books":[{"name":"the alchemist"},  {"name":"the alchemist"}

But what I got was this

{"owner":"princu7", "books":[]}

Upon reading the documentation, it says that pull removes all the instances that match the required condition so maybe that's why it's removing all other entries of the array which match the condition.So what should I do here.Thanks for reading.Really appreciate your help.

3 Answers 3

3

See this issue: https://jira.mongodb.org/browse/SERVER-1014

You cannot achieve what you are trying to do in a single update. A way would be to modify that record in your application & save the changes.

Sign up to request clarification or add additional context in comments.

Comments

2

You could use collection.updateOne() with upsert set to true to re-write the record in place. The idea is you get the original document, modify it in your app logic, then re-apply it to the database after removing the element from the array.

function upsert(collection, query, json) {
    var col = db.collection(collection);
    col.updateOne(query
        , { $set : json }
        , { upsert : true }
        , function (err, result) {
            if(err) {
                log('error = ', err);
            } else {
                // no error, call the next function
            }
        }
    );
};

Comments

1

By design, mongodb's $pull operator removes from an existing array all instances of a value or values that match the specified condition.Therefore it will remove all matching {"name":"the alchemist"} elements from the array.

I guess I would use $pop, which only removes the first matching element.

db.collection("colName")
    .update({"owner": "princu7"}
            , {$pop: {"books": {$match: {"name": "the alchemist"}}}}
            , {multi:false}
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.