'Remove specific object from array during aggregation

I have documents with the following structure:

{field: ["id1", "id3"]},
{field: ["id2", "id1"]}

To query the documents I use

aggregate({$match: {'field' : { $in: ['id1'] }}})

I get the documents with this query but I would like only

{field: ["id2"]},
{field: ["id3"]}

I.e., I want to remove "id1" from the array in the aggregation step only, and not from the actual document (via an update with $pull or something similar).



Solution 1:[1]

Say we have following documents in a collection named collection:

db.collection.insert({field: ["id1", "id3"]})
db.collection.insert({field: ["id2", "id1"]})

Then below aggregation pipeline would do the trick:

db.collection.aggregate([
  {
    $match: {field: "id1"}
  },
  {
    $project: {
      field: {
        $filter: {
          input: "$field",
          as: "item",
          cond: {
            $ne: ["$$item", "id1"]
          }
        }
      }
    }
  }
])

The output from mongo shell is:

{ "field" : [ "id3" ] }
{ "field" : [ "id2" ] }

An alternative way is to $unwind the field and then $group it back:

db.collection.aggregate([
  {
    $match: {field: "id1"}
  },
  {
    $unwind: "$field"
  },
  {
    $group: {
      _id: "$_id",
      field: {
        $push: {
          $cond: {
            if: { $eq: [ "$field", "id1" ] },
            then: "$$REMOVE",
            else: "$field"
          }
        }
      }
    }
  },
  {
    $project: {
      _id: 0
    }
  }
])

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1