I have trouble writing the query to retrieve the last object of the Comments array embedded inside the Story document.
My collection currently looks like this when I
Your "latest" document will always be at the end of your array unless you modify somehow. Adding items into arrays will always go to the "end" or "append" to the existing items when used with the $push operator or added using array manipulation methods in client code.
Only operators like $addToSet or explicitly using modifiers to the $push
operation will change this.
As such, when at the end of an array, what you typically want to do is use $slice, with a negative index to get items from the "end" of the array:
Model.findById("55d3a39565698bbc68079e31")
.select({ "comments": { "$slice": -1 }})
.exec(function(err,doc) {
})
If you have actually modfied the array as mentioned earlier where the latest date is not the last element in the array then you should be using the $sort modifier on updates. It would generally only be "out of place" if you asked for the $position
modifier or you used $addToSet
. The $position
would be deliberate and you cannot also sort, but you can always sort the array after an $addToSet
operation like this, which places the alls the dates in order without changing any other content of the array:
Model.findByIdAndUpdate("55d3a39565698bbc68079e31",
{ "$push": { "comments": { "$each": [], "$sort": { "date": 1 } } } }
)
With the array modified the same $slice
operation applies to queries as the array is now in the order by date.
If however your intention is leave the array in your documents out of order, or in the other order you want, but you also want to get the latest date, then you can use .aggregate() to $sort and retrieve the $last array entry:
Model.aggregate(
[
{ "$match": { "_id": ObjectID("55d3a39565698bbc68079e31") } },
{ "$unwind": "$comments" },
{ "$sort": { "comments.date": 1 } },
{ "$group": {
"_id": "$_id",
"author": { "$first": "$author" },
"link": { "$first": "$link" },
"title": { "$first": "$title" },
"date": { "$first": "$date" },
"comments": { "$last": "$comments" }
}}
]
)
Noting that when using the aggregation framework with mongoose, the _id
"autocasting" that happens in other queries does not happen ( this is by design ), so it is necessary to cast to an ObjectId
value yourself, if the data is not already available in that form and has come in as a string.
Those are your ways of getting the last element ( optionally explicitly sorted ) from an array.