我有一个文章架构,它有一个子文档 comments
,其中包含我为这篇特定文章获得的所有评论。
我要做的是按 id 选择一篇文章,填充其作者字段以及评论中的作者字段。然后按日期对评论子文档进行排序。
文章架构:
var articleSchema = new Schema({
title: { type: String, default: '', trim: true },
body: { type: String, default: '', trim: true },
author: { type: Schema.ObjectId, ref: 'User' },
comments: [{
body: { type: String, default: '' },
author: { type: Schema.ObjectId, ref: 'User' },
created_at: { type : Date, default : Date.now, get: getCreatedAtDate }
}],
tags: { type: [], get: getTags, set: setTags },
image: {
cdnUri: String,
files: []
},
created_at: { type : Date, default : Date.now, get: getCreatedAtDate }
});
文章模式的静态方法:(我想在这里对评论进行排序,我可以这样做吗?)
load: function (id, cb) {
this.findOne({ _id: id })
.populate('author', 'email profile')
.populate('comments.author')
.exec(cb);
},
我必须在别处排序:
exports.load = function (req, res, next, id) {
var User = require('../models/User');
Article.load(id, function (err, article) {
var sorted = article.toObject({ getters: true });
sorted.comments = _.sortBy(sorted.comments, 'created_at').reverse();
req.article = sorted;
next();
});
};
我调用 toObject
将文档转换为 javascript 对象,我可以保留我的 getter/virtuals,但是方法呢??
无论如何,我对普通对象执行排序逻辑并完成。
我很确定有很多更好的方法可以做到这一点,请告诉我。
最佳答案
我本可以把它写成几件事,但考虑到“让 Mongoose 对象回来”似乎是主要考虑因素。
因此,您“可以”做很多事情。但是,由于您正在将引用“填充”到 Object 中,然后想要更改数组中对象的顺序,因此实际上只有一种方法可以一劳永逸地解决这个问题。
在创建数据时按顺序修复数据
如果您希望您的“comments”数组按“created_at”的日期排序,这甚至可以分解为多种可能性:
它“应该”已按“插入”顺序添加,因此“最新”是您注意到的最后一个,但您也可以在最近(过去几年)的版本中“修改”它MongoDB 与
$position
作为$push
的修饰符:Article.update( { "_id": articleId }, { "$push": { "comments": { "$each": [newComment], "$position": 0 } } }, function(err,result) { // other work in here } );
这会将数组元素“添加”到现有数组的“第一个”(0) 索引处,因此它始终位于最前面。
由于逻辑原因或只是在您“想确定”的地方使用“位置”更新失败,那么
$sort
已经存在了更“更长”的时间。$push
的修饰符:Article.update( { "_id": articleId }, { "$push": { "comments": { "$each": [newComment], "$sort": { "$created_at": -1 } } } }, function(err,result) { // other work in here } );
这将对包含指定值的数组元素文档的属性进行“排序”。你甚至可以这样做:
Article.update( { }, { "$push": { "comments": { "$each": [], "$sort": { "$created_at": -1 } } } }, { "multi": true }, function(err,result) { // other work in here } );
这将一次性按指定字段对整个集合中的每个“评论”数组进行排序。
其他解决方案可以使用 .aggregate()
对数组进行排序和/或在您完成该操作或执行您自己的 后“重新转换”为 mongoose 对象。 sort()
在普通对象上。
这两者实际上都涉及创建一个单独的模型对象和“模式”,其中嵌入的项目包括“引用”信息。因此,您可以在这些行上工作,但是当您首先可以将数据排序为“最需要”的意思时,这似乎是不必要的开销。
另一种方法是确保像“virtuals”这样的字段总是“序列化”成一个对象格式,并在调用时使用 .toObject()
并且只是忍受现在所有方法都消失的事实并使用呈现的属性。
最后一种是“理智”的方法,但如果您通常使用的是“created_at”顺序,那么在每次操作中以这种方式“存储”数据更有意义,因此当您“检索”它时,它保持在您将要使用的顺序。
关于node.js - Mongoose 子文档排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31382656/