1

I'm using MongoDB Compass for my queries while searching through a lot of data that I've inherited and quite often being asked to produce reports on the data for various teams but the documents often have too much data for them to easily parse so I'd like to cut down the data being reported on as much as possible

I've got the following example document

{
  "_id": "123456",
  "name": "Bob",
  "date": "2022-07-01",
  "fruit": [
    {
      "_id": "000001",
      "foodName": "apple",
      "colour": "red"
    },
    {
      "_id": "000002",
      "foodName": "apple",
      "colour": "green"
    },
    {
      "_id": "000003",
      "foodName": "banana",
      "colour": "yellow"
    },
    {
      "_id": "000004",
      "foodName": "orange",
      "colour": "orange"
    }
  ]
}

using

db.people.find( { "fruit.foodName" : "apple" } )

returns the whole document

I'd like to search for just the apples so that I get the result:

{
  "_id": "123456",
  "name": "Bob",
  "date": "2022-07-01",
  "fruit": [
    {
      "_id": "000001",
      "foodName": "apple",
      "colour": "red"
    },
    {
      "_id": "000002",
      "foodName": "apple",
      "colour": "green"
    }
  ]
}

Is that possible?

3
  • Does this answer your question? Retrieve only the queried element in an object array in MongoDB collection Commented Oct 26, 2022 at 8:36
  • sort of, db.people.find( {}, { name: 1, fruit: { $elemMatch: { foodname: "apple" } } }) returns just the first element in the array but I would like it to return all of them that match Commented Oct 26, 2022 at 8:48
  • Most of the answers have aggregate options, that would return more than the first element Commented Oct 26, 2022 at 12:26

1 Answer 1

1

You will need to use an aggregation for this and use the $filter operator, The reason you can't use the query language for this is because their projection options are limited and only allow the projection of a single array element, because in your case the array can contain more than 1 matching subdocument it won't do.

You can read more about query language projections here

db.collection.aggregate([
  {
    $match: {
      "fruit.foodName": "apple"
    }
  },
  {
    $addFields: {
      fruit: {
        $filter: {
          input: "$fruit",
          cond: {
            $eq: [
              "$$this.foodName",
              "apple"
            ]
          }
        }
      }
    }
  }
])

Mongo Playground

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

1 Comment

This is life changing, thank you :)

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.