mongodbembedded-documents

How to bring back only nested documents fitting filter


I have created a mongodb collection where the schema is as follows.

{user_id, listings: <Array of Documents>, ...}

In the listing documents I have a field named status which has two values publish and draft.

In mongo shell I am trying to bring back only the user listings with status:publish So I run the bellow command and I keep getting back also documents with status:draft that are part of the user with published listings.

db.properties.find({'listings.status':'publish'},{'listings.status':1, _id:0})

Outputs:

[
  { listings: [ { status: 'draft' } ] },
  { listings: [ { status: 'publish' } ] },
  { listings: [ { status: 'draft' }, { status: 'publish' }, { status: 'draft' } ] },
  { listings: [ { status: 'publish' }, { status: 'draft' } ] },
  { listings: [ { status: 'publish' } ] }
]

How can I get an array back of the listings with only status: publish ?


Solution

  • You can use an aggregation pipeline with a $filter:

    1. $filter the listings field to contain only items with status publish.
    2. $match only documents with $size of listings greater than 0.
    3. format
    db.collection.aggregate([
      {
        $set: {
          listings: {
            $filter: {
              input: "$listings",
              as: "item",
              cond: {
                $eq: [
                  "$$item.status",
                  "publish"
                ]
              }
            }
          }
        }
      },
      {$match: {$expr: {$gt: [{$size: "$listings"}, 0]}}},
      {$project: {listings: 1, _id: 0}}
    ])
    

    Playground example