如何在Mongoose中检索嵌入文档中数组的最后一个对象?

Ste*_*hen 3 mongoose mongodb node.js mongodb-query

我在编写查询时遇到问题,无法检索Story文档中嵌入的Comments数组的最后一个对象.

当我执行db.stories.find()时,我的集合目前看起来像这样:

{
"_id" : ObjectId("55d3a39565698bbc68079e31"),
"author" : "Steven Chen",
"link" : "COCO",
"title" : "COCO",
"date" : ISODate("2015-08-18T21:28:53.629Z"),
"comments" : [
    {
        "author" : "Steven",
        "text" : "Major",
        "_id" : ObjectId("55d3a39565698bbc68079e32"),
        "date" : ISODate("2015-08-18T21:28:53.632Z")
    },
    {
        "text" : "Canada",
        "author" : "Steven",
        "_id" : ObjectId("55d3a39a65698bbc68079e33"),
        "date" : ISODate("2015-08-18T21:28:58.001Z")
    },
    {
        "text" : "Usa",
        "author" : "Steven",
        "_id" : ObjectId("55d3a39c65698bbc68079e34"),
        "date" : ISODate("2015-08-18T21:29:00.877Z")
    }
],
"__v" : 0
}
Run Code Online (Sandbox Code Playgroud)

我想根据Story文档的_id给出的日期检索最后一条评论.

我的代码的上下文是有一个带有注释列表的Story帖子,我想检索最后的注释并使用ajax将其作为JSON发送到我的客户端JS,以便可以使用最新/最新注释更新视图.

在这种情况下,带有"text:"Usa"的评论应该是获取的评论.

有人可以提供正确的方法来做到这一点,如果你能解释原因会更好吗?谢谢!

Bla*_*ven 12

除非您以某种方式进行修改,否则您的"最新"文档将始终位于数组的末尾.当与$push运算符一起使用或在客户端代码中使用数组操作方法添加时,将项添加到数组中将始终转到现有项的"结束"或"附加" .

只有操作员喜欢$addToSet或明确使用操作符的修饰符$push才会改变这一点.

因此,当在数组的末尾时,您通常要使用的$slice是负数索引来从数组的"结尾"获取项目:

Model.findById("55d3a39565698bbc68079e31")
    .select({ "comments": { "$slice": -1 }})
    .exec(function(err,doc) {

    })
Run Code Online (Sandbox Code Playgroud)

如果您实际修改了前面提到的数组,其中最新日期不是数组中的最后一个元素,那么您应该$sort在更新时使用修饰符.如果你要求使用$position修饰符,它通常只会"不合适" $addToSet.这$position是故意的,你也不能排序,但你总是可以在这样的$addToSet操作之后对数组进行排序,这样就可以将所有日期按顺序排列,而不会更改数组的任何其他内容:

Model.findByIdAndUpdate("55d3a39565698bbc68079e31",
   { "$push": { "comments": { "$each": [], "$sort": { "date": 1 } } } }
)
Run Code Online (Sandbox Code Playgroud)

修改了数组后,同样的$slice操作适用于查询,因为数组现在按日期排序.

然而,如果你的目的是留在你的文件排列出顺序,或者你想要的其他命令,但你也想获得最新的日期,那么你可以使用.aggregate()$sort和检索$last数组项:

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" }
        }}
    ]
)
Run Code Online (Sandbox Code Playgroud)

注意到当使用带有_idmongoose 的聚合框架时,其他查询中发生的"自动调用"不会发生(这是设计),因此ObjectId如果数据尚未以该形式提供,则必须自己转换为值并以字符串形式出现.

这些是从数组中获取最后一个元素(可选地显式排序)的方法.