How to retrieve an array's last object in an embedded document in Mongoose?

前端 未结 1 1505
春和景丽
春和景丽 2021-01-03 11:44

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

相关标签:
1条回答
  • 2021-01-03 12:20

    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.

    0 讨论(0)
提交回复
热议问题