我无法编写查询来检索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
}
我希望根据Story文档的_id给出的日期检索最后一条评论。
我的代码的上下文是有一个带有注释列表的Story帖子,我想检索最后的注释并使用ajax将其作为JSON发送到我的客户端JS,以便可以使用最新的/更新视图最新评论。
在这种情况下,带有“text:”Usa“的评论应该是被检索的评论。
有人能提供正确的方法来做到这一点,如果你能解释原因会更好吗?谢谢!
答案 0 :(得分:12)
您最近的"除非您以某种方式修改,否则文档将始终位于数组的末尾。将项目添加到数组中将始终转到" end"或"追加"与$push
运算符一起使用时的现有项目,或者在客户端代码中使用数组操作方法添加的项目。
只有像$addToSet
这样的操作符或明确使用$push
操作的修饰符才会改变这一点。
因此,当在数组的末尾时,您通常要做的是使用$slice
,使用负索引来从" end"中获取项目。数组:
Model.findById("55d3a39565698bbc68079e31")
.select({ "comments": { "$slice": -1 }})
.exec(function(err,doc) {
})
如果您实际修改了前面提到的数组,其中最新日期不是数组中的最后一个元素,那么您应该在更新时使用$sort
修饰符。它通常只会出现“不合适”的情况。如果您要求$position
修饰符,或者您使用了$addToSet
。 $position
是故意的,你也不能排序,但你总是可以在这样的$addToSet
操作之后对数组进行排序,这样就可以按顺序排列所有日期而不更改数组的任何其他内容:
Model.findByIdAndUpdate("55d3a39565698bbc68079e31",
{ "$push": { "comments": { "$each": [], "$sort": { "date": 1 } } } }
)
修改了数组后,同样的$slice
操作适用于查询,因为数组现在按日期排序。
但是,如果您的意图是将文档中的数组不按顺序排列,或者按照您想要的其他顺序,但您也希望获得最新日期,那么您可以使用.aggregate()
{{3}并检索$sort
数组条目:
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" }
}}
]
)
注意到当使用带有mongoose的聚合框架时,_id
" autocasting"在其他查询中发生的情况不会发生(这是设计),因此如果数据尚未以该表单形式提供并且以字符串形式出现,则必须自己转换为ObjectId
值。< / p>
这些是从数组中获取最后一个元素(可选地显式排序)的方法。