Home > Mobile >  How to filter and get required data from a nested document in MongoDB?
How to filter and get required data from a nested document in MongoDB?

Time:12-01

I have this structure in my DB.

[
  {
    _id: ObjectId("6386ef039775398be3620c76"),
    firstName: 'A',
    lastName: 'BA',
    age: 34,
    history: [
      { disease: 'fever', cured: true },
      { disease: 'malaria', cured: false }
    ]
  },
  {
    _id: ObjectId("6386ef239775398be3620c77"),
    firstName: 'AA',
    lastName: 'BA',
    age: 24,
    history: [
      { disease: 'cold', cured: true },
      { disease: 'thyroid', cured: false }
    ]
  }
]

What i'm tying to achieve is a query which will get me data like this:

Query

 db.collection.find({$filter:{history:{$elemMatch:{cured:false}}}

Expected Result:

[
  {
    _id: ObjectId("6386ef039775398be3620c76"),
    firstName: 'A',
    lastName: 'BA',
    age: 34,
    history: [
      { disease: 'malaria', cured: false }
    ]
  },
  {
    _id: ObjectId("6386ef239775398be3620c77"),
    firstName: 'AA',
    lastName: 'BA',
    age: 24,
    history: [
      { disease: 'thyroid', cured: false }
    ]
  }
]

What i have tried is

1.

db.collection.find({$filter:{history:{$elemMatch:{cured:false}}}
db.collection.aggregate([{$project:{history:{$filter:{input:"$history",as:"items",cond:{cured:false}}}}}])
db.collection.find({history:{$elemMatch:{cured:true}}},{'history.cured':1})

But none of these queries are giving desired result, Doubts/ Questions

  1. Is it possible to get expected result straight from a query?
  2. Where my queries went wrong?
  3. What material should i go through to cover more advance concepts related to this query?

Any help would be much appreciated. My apologies if this question is too basic.

CodePudding user response:

One option is to merge your query attempts to:

  1. Get all documents that have an item with cured: false
  2. $filter history array to include only such items
db.collection.aggregate([
  {$match: {
      history: {$elemMatch: {cured: false}}
  }},
  {$set: {
      history: {
        $filter: {
          input: "$history",
          cond: {$eq: ["$$this.cured", false]}
        }
      }
  }}
])

See how it works on the playground example

  • Related