3

Supose a database containing something like that

{  
   "grades":[  
      {  
         "grade":"A",
         "score":2
      },
      {  
         "grade":"A",
         "score":6
      },

   ],
   "name":"Morris Park Bake Shop"
},
{  
   "grades":[  
      {  
         "grade":"A",
         "score":8
      },
      {  
         "grade":"B",
         "score":23
      }
   ],
   "name":"Wendy'S"
}

How can I apply a filter that will just return the restaurants where ALL grades are "A"?

If I try db.restaurants.find({ "grades.grade" : "A" } ), the way it works is that it search for ANY grade inside my element.

I tried using aggregate with unwind to, but it do the same thing, it opens grades, filter, and returns any match of restaurant...

1

1 Answer 1

2

In your situation I would do something like this :

db.getCollection('test').aggregate([
{$unwind:"$grades"},
    { $group: { 
        _id: '$_id', 
        grades : { $first: '$grades' },  
        all_grades: { $sum: 1 },
        all_grades_that_match: { $sum: { $cond: [ { $eq: [ '$grades.grade', "A" ] }, 1, 0 ] } },     
        name: { $first: '$name' }     
    }},
   { $project: {
        _id: 1,
        name: 1,
        grades: 1,
        arrays_equal: { $cond: [ { $eq: [ '$all_grades', '$all_grades_that_match' ] }, 1, 0 ] }
    }},
    { $match: { 'arrays_equal' : 1 } } 
])

The group operation will count the total number of grades and the number of grades that match you query, the projection will compare those two results to see if they are equal, finally, the match operation will only keep the ones where arrays_equal is true

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

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.