Does "$eq" aggregation operator works with array dot notation?

I think, "$data.0.val1" is not a correct expression in aggregation, when used with array fields. To get the data array’s first element’s val1 value, you need something like this using the aggregation operator $arrayElemAt. For example,

db.test.aggregate([ { $project: { first_ele: { $arrayElemAt: [ "$data", 0 ] } } } ])

returns two documents with first element of the array:

{ "_id" : 1, "first_ele" : { "val1" : "xyz", "val2" : "abc" } }
{ "_id" : 2, "first_ele" : { "val1" : "d", "val2" : "e" } }

Then, you can match with a specific field within the first_ele:
{ $match: { "first_ele.val1": "xyz" } }

This returns the document with _id: 1, the expected result.

So, the aggregation with both stages would be:

db.test.aggregate([
  { $addFields: { first_ele: { $arrayElemAt: [ "$data", 0 ] } } },
  { $match: { "first_ele.val1": "xyz" } }
])

Alternative, using $match with $expr:

db.test.aggregate([
  { $match: { 
      $expr: {
          $eq: [ { 
              $reduce: { 
                   input: [ { $arrayElemAt: [ "$data", 0 ] } ], 
                   initialValue: false,
                   in: { $eq: [ "$$this.val1", "xyz" ] }
              } }, 
              true 
          ]
      }
  } }
]).pretty()

This query with the $expr used with find works fine:

db.test.find( { 
  $expr: { 
    $eq: [ { 
        $reduce: { 
            input: [ { $arrayElemAt: [ "$data", 0 ] } ], 
            initialValue: false,
            in: { $eq: [ "$$this.val1", "xyz" ] }
        } }, 
        true 
    ]
  } 
}).pretty()
1 Like