Mongoose怎么样对嵌套数组进行排序和筛选操作?
发布于 8 年前 作者 gzlock 7289 次浏览 来自 问答

我主要通过搜索各种Mongoose的代码例子来学习,但对于嵌套数组的排序和筛选操作搜不到,特来请教。

Article = new Schema({
//blablabla 其它数据
comments: [{content: String, time: {type: Number, default: Date.now}}],//直接就是数组数据,没有为comment建一个Schema,有必要建一个吗?
}, {strict: true});

comments的time的数据类型是13位时间戳数字 想对comments数组进行time排序(正序或倒序),以及按time所处于的日子显示(例如 time处于 今天的凌晨和23:59:59之间就视为是今天的评论)。

如果在用mysql,我会为comments建一个表,每条comment都有文章id,这种关系在MongoDB上该怎么样转变和实现呢?

8 回复

额,好像没有接口能对一个记录里面的内嵌数组进行查询和排序吧,除非说查询到这条记录后,在js里面对这个数组进行操作。 ps: 如果评论数很多并且需要做排序啊筛选的操作的,最好还是新建一个 Comment Schema :

let CommentSchema = new Schema({
  articleId: ObjectId,
  content: String,
  time: {type: Number, default: Date.now}
});

@imziyang 那如果想摆脱关系型数据库的思想,把CommentSchema内嵌到Article的comments数组呢 该怎么样对CommentSchema筛选?

我还是按关系型去做算了。。。 Mongoose的sub document太麻烦了。。。

@gzlock 嗯,思维也不用完全固化,觉得mongodb就完全是nosql,就绝对不能使用关系型的结构~还是根据业务需求吧,个人觉得,可控长度的数据放在内嵌是很完美的,拿出来也很快,一直在增长的数据还是单独拿出来比较好~~具体选择的话也是根据需求吧~

mongodb 中单个文档最大是16M,如果acticle有比较多的评论内嵌到acticle模型中是不合适的,类比cnode社区,针对帖子topic专门建立了对应的reply模型

@imziyang @herohenu 感谢回复 还有一个问题搜不到答案

model.findOneAndUpdate(query,update);

update参数怎么样写可以直接让文章的浏览量+1? 我搜到MongoDB文档里,aggregation有$add的用法

{ "_id" : 1, "item" : "abc", "price" : 10, "fee" : 2, date: ISODate("2014-03-01T08:00:00Z") }
{ "_id" : 2, "item" : "jkl", "price" : 20, "fee" : 1, date: ISODate("2014-03-01T09:00:00Z") }
{ "_id" : 3, "item" : "xyz", "price" : 5,  "fee" : 0, date: ISODate("2014-03-15T09:00:00Z") }

db.sales.aggregate(
   [
     { $project: { item: 1, total: { $add: [ "$price", "$fee" ] } } }
   ]
)

但不符合我的需求,是不是只能先findOne把文章找出来,然后浏览量+1再save?

@gzlock 先find出来加1也是可以的, 但也可以使用$inc操作符,假设你的模型里有个 viewCount字段,那可以:

model.update({
  _id: '文章id',
}, {
  $inc: {
    viewCount: 1
  }
}, callback)

ps: 上面的update替换成findOneAndUpdate或者findByIdAndUpdate也可以,update参数内容都一样,只有第一个参数不一样而已~

在更新的时候使用$sort

https://docs.mongodb.org/manual/reference/operator/update/sort/

  {
	$push: {
	   <field>: {
		 $each: [ <value1>, <value2>, ... ],
		 $sort: <sort specification>
	   }
	}
  }
  
回到顶部