2

I have a Document in MongoDB with a list of Embedded Documents. let's take a simplified example of a car document with a list of tires:

{
    "make": "Toyota",
    "color": "blue",
    "tires": [{
        "make": "Mishlen",
        "size": 185
    }, {
        "make": "Mishlen",
        "size": 210
    }]
}

When I ran the following query to find all cars with tire size below 200 I get the same document back but I don't know which of the tires matched the query.

{"tires.size": {$gt: 200}}

I'm trying to achive some kind of this result back:

{
    "make": "Toyota",
    "color": "blue",
    "tires": [{
        "make": "Mishlen",
        "size": 185,
        "matched": true
    }, {
        "make": "Mishlen",
        "size": 210,
        "matched": false
    }]
}

This way I can tell which of the tires matched my query. What is the best way to achive this kind of result? in terms of performance.

Michael Royf
  • 127
  • 6
  • add how is your query – GiovaniSalazar Dec 28 '19 at 04:32
  • add what? can u explain? – Michael Royf Dec 28 '19 at 04:40
  • "When I ran a query to find all cars..." ..how is your query ? – GiovaniSalazar Dec 28 '19 at 04:48
  • Does this answer your question? [How to filter array in subdocument with MongoDB](https://stackoverflow.com/questions/15117030/how-to-filter-array-in-subdocument-with-mongodb) or this (https://stackoverflow.com/questions/3985214/retrieve-only-the-queried-element-in-an-object-array-in-mongodb-collection) – whoami - fakeFaceTrueSoul Dec 28 '19 at 05:22
  • The solution suggested only return the list and id and not the entire document. I would like to receive the entire document with a filtered list or the entire document with a full list and an extra field( list the suggested return in my post). I hope that make sense – Michael Royf Dec 28 '19 at 06:20
  • @MichaelRoyf : Ok you need to use `$addFields` instead of `$project`, Please check my answer.Haven't tested it - but it should work for you, let me know if there are any issues.. – whoami - fakeFaceTrueSoul Dec 28 '19 at 07:42

2 Answers2

1

Please try this :

db.yourCollectionName.aggregate([
    { $addFields: {
        tires: {$filter: {
            input: '$tires',
            as: 'each',
            cond: {$lt: ['$$each.size', 200]}
        }}
    }}
])

Collection Data :

{
    "make": "Toyota",
    "color": "blue",
    "tires": [{
        "make": "Mishlen",
        "size": 185
    }, {
        "make": "Mishlen",
        "size": 210
    }]
}

Result :

{
    "make": "Toyota",
    "color": "blue",
    "tires": [{
        "make": "Mishlen",
        "size": 185
    }]
}

Ref : $addFields , $filter

whoami - fakeFaceTrueSoul
  • 17,086
  • 6
  • 32
  • 46
0

You can use $cond (aggregation) to add a new Boolean value.

db.collection.aggregate([
  {
    $addFields: {
      tires: {
        $map: {
          input: "$tires",
          in: {
            make: "$$this.make",
            size: "$$this.size",
            matched: {
              $cond: {
                if: {
                  $lt: [
                    "$$this.size",
                    200
                  ]
                },
                then: true,
                else: false
              }
            }
          }
        }
      }
    }
  }
])

Results:

[
  {
    "color": "blue",
    "make": "Toyota",
    "tires": [
      {
        "make": "Mishlen",
        "matched": true,
        "size": 185
      },
      {
        "make": "Mishlen",
        "matched": false,
        "size": 210
      }
    ]
  }
]

Live demo: MongoPlayground

user9408899
  • 4,202
  • 3
  • 19
  • 32