node.js - Mongoose 子文档排序

标签 node.js mongodb mongoose

我有一个文章架构,它有一个子文档 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”的日期排序,这甚至可以分解为多种可能性:

  1. 它“应该”已按“插入”顺序添加,因此“最新”是您注意到的最后一个,但您也可以在最近(过去几年)的版本中“修改”它MongoDB 与 $position作为 $push 的修饰符:

    Article.update(
        { "_id": articleId },
        { 
            "$push": { "comments": { "$each": [newComment], "$position": 0 } }
        },
        function(err,result) {
            // other work in here
        }
    );
    

    这会将数组元素“添加”到现有数组的“第一个”(0) 索引处,因此它始终位于最前面。

  2. 由于逻辑原因或只是在您“想确定”的地方使用“位置”更新失败,那么 $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/

相关文章:

node.js - fetch 方法未在 React 中使用 ES6 fetch 定义

mongodb - 不存在的服务 "fos_user.doctrine_registry"

node.js - 检查数组中是否存在未知字段

node.js - NodeJS + Passport + 多个服务器上的 session

Node.js kafka-node 分区器类型用法

node.js - 声明 mongoose.Schema.Types.ObjectId 的目的是什么?

node.js - 如何立即加载更改 - React Native

javascript - mongodb 和 node.js 驱动程序未连接聊天休息 api

mongodb - ( react 性)Mongo 测试失败,返回 : unrecognised field 'snapshot'

typescript - Nest.js/ Mongoose : Why is my pre save hook failing to be triggered?