Consider a document containing an array of embedded documents:
{'array': [{'key1': 120.0, 'key2': 69.0}, {'key1': 100.0, 'key2': 50.0}]}
I want to project key2
for the first element of the array.
I naively tried
'$project':
{
'item': '$array.0.key2'
}
which fails (but explains what I want to do better than many words).
Since MongoDB 3.2, it is possible to get an item from the list using $arrayElemAt:
'$project':
{
'item1': {'$arrayElemAt': ['$array', 0] }
}
will return item1
as {'key1': 120.0, 'key2': 69.0}
.
What I want key2
in there.
I managed to get it using $let:
'$project':
{
'item': {
'$let': {
'vars': {
'tmp': {'$arrayElemAt': ['$array', 0] },
},
'in': '$$tmp.key2'
}
},
}
This seems painfully verbose. Especially considering I'd like to use this construction in several expressions for the same value (test not zero, then use in division) in the same projection.
The array stores the successive states of the object represented in the document, sorted by date, reverse order. The 1st element of the array is the last (therefore current) state. I want to sort the documents using a ratio of two values in the current state.
It is possible that the only reasonable solution would be to get the last state out of the array. Or even to pre-calculate the ratio and sort on the pre-calculated value.
Use the Array Index to Query for a Field in the Embedded Document. Using dot notation, you can specify query conditions for field in a document at a particular index or position of the array. The array uses zero-based indexing. When querying using dot notation, the field and index must be inside quotation marks.
Accessing embedded/nested documents – In MongoDB, you can access the fields of nested/embedded documents of the collection using dot notation and when you are using dot notation, then the field and the nested field must be inside the quotation marks.
To search the array of object in MongoDB, you can use $elemMatch operator. This operator allows us to search for more than one component from an array object.
In an aggregation pipeline you can repeat steps to keep things cleaner so after:
'$project': {'item1': {'$arrayElemAt': ['$array', 0] }}
you can add:
{$project: {"item1.key2": 1}}
Actually you don't need to use the $let
operator to do this. Simply use the $arrayElemAt
operator in your $project
stage to return the first item in your "array" and the $$ROOT
system variable to return the current document. From there you can easily specify the field to $sort
by using the dot notation. Additionally you can add another $project
stage to the pipeline to discard the "item" field and the "_id" field from the query result.
db.collection.aggregate([
{ "$project": {
"item": { "$arrayElemAt": [ "$array", 0 ] },
"doc": "$$ROOT"
}},
{ "$sort": { "item.key2": 1 } },
{ "$project": { "doc": 1, "_id": 0 } }
])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With