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()