2
{
"_id" : ObjectId("5488303649f2012be0901e97"),
"user_id":3,
"my_shopping_list" : {
    "books" : [ ]
},
"my_library" : {
    "books" : [
        {
            "date_added" : ISODate("2014-12-10T12:03:04.062Z"),
            "tag_text" : [
                "english"
            ],
            "bdata_product_identifier" : "a1",
            "tag_id" : [
                "fa7ec571-4903-4aed-892a-011a8a411471"
            ]
        },
        {
            "date_added" : ISODate("2014-12-10T12:03:08.708Z"),
            "tag_text" : [
                "english",
                "hindi"
            ],
            "bdata_product_identifier" : "a2",
            "tag_id" : [
                "fa7ec571-4903-4aed-892a-011a8a411471",
                "60733993-6b54-420c-8bc6-e876c0e196d6"
            ]
        }
    ]
},
"my_wishlist" : {
    "books" : [ ]
},

}

Here I would like to remove only english from every tag_text array of my_library using only user_id and tag_text This document belongs to user_id:3. I have tried some queries which delete an entire book sub-document . Thank you.

2
  • Have you looked at using $pull? Commented Dec 10, 2014 at 14:24
  • @JohnnyHK Yes. But the syntax I used was wrong. Query was deleting entire sub document that contains the tag_text Commented Dec 11, 2014 at 4:42

2 Answers 2

1

Well since you are using pymongo and mongodb doesn't provide a nice way for doing this because using the $ operator will only pull english from the first subdocument, why not write a script that will remove english from every tag_text and then update your document.

Demo:

>>> doc = yourcollection.find_one(
    {
        'user_id': 3, "my_library.books" : {"$exists": True}},
        {"_id" : 0, 'user_id': 0
    })

>>> books = doc['my_library']['books'] #books field in your doc
>>> new_books = []

>>> for k in books:
...     for x, y in k.items():
...         if x == 'tag_text' and 'english' in y:
...             y.remove('english')
...         new_book.append({x:y})
... 
>>> new_book
[{'tag_text': []}, {'tag_id': ['fa7ec571-4903-4aed-892a-011a8a411471']},   {'bdata_product_identifier': 'a1'}, {'date_added': datetime.datetime(2014, 12, 10, 12, 3, 4, 62000)}, {'tag_text': ['hindi']}, {'tag_id': ['fa7ec571-4903-4aed-892a-011a8a411471', '60733993-6b54-420c-8bc6-e876c0e196d6']}, {'bdata_product_identifier': 'a2'}, {'date_added': datetime.datetime(2014, 12, 10, 12, 3, 8, 708000)}]

>>> yourcollection.update({'user_id' : 3}, {"$set" : {'my_library.books' : bk}})

Check if everything work fine.

>>> yourcollection.find_one({'user_id' : 3})
{'user_id': 3.0, '_id': ObjectId('5488303649f2012be0901e97'), 'my_library': {'books': [{'tag_text': []}, {'tag_id': ['fa7ec571-4903-4aed-892a-011a8a411471']}, {'bdata_product_identifier': 'a1'}, {'date_added': datetime.datetime(2014, 12, 10, 12, 3, 4, 62000)}, {'tag_text': ['hindi']}, {'tag_id': ['fa7ec571-4903-4aed-892a-011a8a411471', '60733993-6b54-420c-8bc6-e876c0e196d6']}, {'bdata_product_identifier': 'a2'}, {'date_added': datetime.datetime(2014, 12, 10, 12, 3, 8, 708000)}]}, 'my_shopping_list': {'books': []}, 'my_wishlist': {'books': []}}
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you. Its the only solution. Mongodb does not provide the the functionality to delete english from every sub document
Answer accepted. Yes like you said the placeholder will pull english from only first sub document.
I do not have enough reputation to upvote. Ur answer is accepted
1

One possible solution could be to repeat

db.collection.update({user_id: 3, "my_library.books.tag_text": "english"}, {$pull: {"my_library.books.$.tag_text": "english"}}

until MongoDB can no longer match a document to update.

1 Comment

Thanku for the answer. It's partially correct. It removes english from tag_text array only from first sub-document(here only of "a1" bdata_product identifier).

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.