0

I have the followng json file

{
  "movies": [{
    "title" : "Star Wars: Episode I - The Phantom Menace",
    "episode_number" : "1",
    "main_characters" : ["Qui-Gon Jinn", "Obi-Wan Kenobi"],
    "description" : "The evil Trade Federation, led by Nute Gunray is planning to take over the peaceful world of Naboo. ",
    "poster" : "star_wars_episode_1_poster.png",
    "hero_image" : "star_wars_episode_1_hero.jpg"
  },

  {
    "title" : "Star Wars: Episode II - Attack of the Clones",
    "episode_number" : "2",
    "main_characters" : ["Obi-Wan Kenobi", "Anakin Skywalker"],
    "description" : "Ten years after the 'Phantom Menace' threatened the planet Naboo, Padmé Amidala is now a Senator representing her homeworld.",
    "poster" : "star_wars_episode_2_poster.png",
    "hero_image" : "star_wars_episode_2_hero.jpg"
  }
]
}

The collection name is fruits

I am trying to extract only the data for episode_number = 2. I have tried following queries

db.fruits.find({"movies": {$elemMatch:{"episode_number": "2"}}}).pretty();

which returns the entire document instead of just the data for episode_number 2.

and

db.fruits.find({"movies.episode_number": "2"}}}).pretty();

which also returns the entire document including that for episode_number 1

I am trying to figure out how to query this document so that only the data for episode_number = 2 is returned.

Please help.

Niraj
  • 333
  • 1
  • 5
  • 23
  • It looks like your `movies` object should be another collection in db. Now each `fruit` document has `movies` array field, is it by design? If you really need such db design so with `find` query it is not possible to return array element, you should use aggregation pipeline, but it will be really expensive query – Max Sinev May 24 '18 at 15:43
  • Sorry I should have specified, the collection name is fruits – Niraj May 24 '18 at 15:48

2 Answers2

0

find method takes two parameters: first one represents filtering condition and second one is for projection. To get one element from your array you can use $elemMatch in projection part:

db.fruits.find(
   {"movies.episode_number": "2"}, 
   {"movies": {$elemMatch:{"episode_number": "2"}}})
.pretty();

So first parameter filters out your collection and second one filters inner array

mickl
  • 48,568
  • 9
  • 60
  • 89
  • For filtering part it can be `{"movies.episode_number": "2"}` as well. And this query returns documents with `movies` array with single element, but I think it's better than building big aggregation pipeline. – Max Sinev May 24 '18 at 16:05
  • Right, I will simplify this, thanks @MaxSinev – mickl May 24 '18 at 16:09
0

If you want all documents in the collection with movies array but it should contain only episode 2 details in it you need to filter the array.

https://docs.mongodb.com/manual/reference/operator/aggregation/filter/ or use $unwind, $match.

db.fruits.aggregate
([
  {
      $unwind: '$movies'
  },

  {
      $match:{"movies.episode_number":'2'}

  }

])