Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

107
Views
How to list only matched subdocuments in Mongoose

I'm new in mongoose. I tried many queries but couldn't get correct result. My schema looks like this:

{
 course_name: "Test 1",
 students: [
  {name: "Sam", age: 5},
  {name: "Don", age: 7}
 ]
},
{
 course_name: "Test 2",
 students: [
  {name: "Paul", age: 7}
 ]
}

In this example I have 2 documents. Every course document contains students data inside of it. I'm trying to find all students in all courses which their ages are 7. But in queries I tried, it returns Sam too.

Here's an example of which I'm expecting:

{name: "Paul", age: 7},
{name: "Don", age: 7}

And here's what I'm getting.

{name: "Paul", age: 7},
{name: "Sam", age: 5},
{name: "Don", age: 7}

My query:

const getStudents = await Courses.aggregate([
    {$match: {'students.age': myAge}},
    {$unwind: '$students'},
    {$project: {name: '$students.name', age: '$students.age'}}
  ]);

Thanks for your time

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Is a common mistake think that if you match by a nested value (in this case students.age) you will get the nested value you want but it doesn't work like this.

You are doing $match query before $unwind so you are getting all documents where exists any object into students array where age is 7. That is, the whole document1 pass to the next stage. The array students with two values go to next tsage because one of them match the criteria and then, the object is matched.

So, to be clearer, you are doing a $match stage where you are saying: "Give me all documents where exist an student which age is 7". Then, the first document match the criteria because one of the students match the filter, and is returned the whole document, not only the object in the array that matches.

You can match after the unwind and you will get the desired output.

Example here

over 4 years ago · Santiago Trujillo Report

0

@J.F. does a good job explaining why your approach is not correct. Anyway i want to show you how you can achieve the same result using the $filter.

Selects a subset of an array to return based on the specified condition. Returns an array with only those elements that match the condition. The returned elements are in the original order.

db.collection.aggregate({
  $addFields: {
    students: {
      $filter: {
        input: "$students",
        as: "student",
        cond: {
          $eq: [
            "$$student.age",
            7
          ]
        }
      }
    }
  }
})

Result:

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "course_name": "Test 1",
    "students": [
      {
        "age": 7,
        "name": "Don"
      }
    ]
  },
  {
    "_id": ObjectId("5a934e000102030405000001"),
    "course_name": "Test 2",
    "students": [
      {
        "age": 7,
        "name": "Paul"
      }
    ]
  }
]
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!