1

Let's imagine a mongo collection of - let's say magazines. For some reason, we've ended up storing each issue of the magazine as a separate document. Each article is a subdocument inside an Articles-array, and the authors of each article is represented as a subdocument inside the Writers-array on the Article-subdocument. Only the name and email of the author is stored inside the article, but there is an Writers-array on the magazine level containing more information about each author.

{
   "Title": "The Magazine",
   "Articles": [
     {
       "Title": "Mongo Queries 101",
       "Summary": ".....",
       "Writers": [
         {
           "Name": "tom",
           "Email": "[email protected]"
         },
         {
           "Name": "anna",
           "Email": "[email protected]"
         }
        ]
     },
     {
       "Title": "Why not SQL instead?",
       "Summary": ".....",
       "Writers": [
         {
           "Name": "mike",
           "Email": "[email protected]"
         },
         {
           "Name": "anna",
           "Email": "[email protected]"
         }
        ]         
      }
   ],
  "Writers": [
     {
       "Name": "tom",
       "Email": "[email protected]",
       "Web": "tom.example.com"
     },
     {
       "Name": "mike",
       "Email": "[email protected]",
       "Web": "mike.example.com"
     },
     {
       "Name": "anna",
       "Email": "[email protected]",
       "Web": "anna.example.com"
     }
   ]
}

How can one author be completely removed from a magazines?

Finding magazines where the unwanted author exist is quite easy. The problem is pulling the author out of all the sub documents.

MongoDB 3.6 introduces some new placeholder operators, $[] and $[<identity>], and I suspect these could be used with either $pull or $pullAll, but so far, I haven't had any success.

Is it possible to do this in one go? Or at least no more than two? One query for removing the author from all the articles, and one for removing the biography from the magazine?

3
  • Can you please provide me a sample data set? Commented Mar 22, 2018 at 20:45
  • I've extended the samle doc a little bit. It should be enough. Try removing { "Name": "tom", "Email": "[email protected]" } from the doc. Commented Mar 22, 2018 at 20:59
  • You'll need to match both Name and Email. Alone, neither is not enough. Commented Mar 22, 2018 at 21:01

1 Answer 1

1

You can try below query.

db.col.update(
  {},
  {"$pull":{
    "Articles.$[].Writers":{"Name": "tom","Email": "[email protected]"},
    "Writers":{"Name": "tom","Email": "[email protected]"}
  }},
  {"multi":true}
);
Sign up to request clarification or add additional context in comments.

10 Comments

I didn't expect that to work when I first read the answer, but after trying it out it did work. But how?? I would at least expected that the Articlesand Writers-parts would have needed to be separated some how. Can you explain?
$pull operator takes document with key (array field) and value (query criteria) pair. The first key value part is to update the Writers array inside the Articles, which is key, using positional all operator with the value as query condition. The second key value part is to update Writers array outside of Articles, which is key, using query condition as value.
@Veeram Why do we need to go for Articles.$[].Writers instead of Articles.$.Writers here?
And BOOM! Now that the query is defined, it turns out that mlabs still doesn't provide 3.6 databases. Not even in sandboxes. Same problem every time there is a new mongo version. Takes forever before mLabs provides support. Guess this is the year we'll have to drop them...
@Rahul Raj To be honest I just looked at anna record in two arrays and assumed that OP wanted to remove from all arrays. If Op wanted it to remove from single array I can update the answer to reflect that.
|

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.