猫鼬子文档排序 [英] mongoose subdocument sorting

查看:68
本文介绍了猫鼬子文档排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个文章架构,其中包含一个子文档comments,其中包含我对此特定文章的所有评论.

I have an article schema that has a subdocument comments which contains all the comments i got for this particular article.

我想做的是按ID选择文章,填充其author字段,并在注释中填充author字段.然后按日期对注释子文档进行排序.

What i want to do is select an article by id, populate its author field and also the author field in comments. Then sort the comments subdocument by date.

文章架构:

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 }
});

文章架构上的静态方法:(我想在这里对评论进行排序,我可以这样做吗?)

static method on article schema: (i would love to sort the comments here, can i do that?)

  load: function (id, cb) {
    this.findOne({ _id: id })
      .populate('author', 'email profile')
      .populate('comments.author')
      .exec(cb);
  },

我必须在其他地方对它进行排序:

I have to sort it elsewhere:

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对象,我可以保留我的getters/virtuals,但是方法呢?

I call toObject to convert the document to javascript object, i can keep my getters / virtuals, but what about methods??

无论如何,我对普通对象执行排序逻辑并完成操作.

Anyways, i do the sorting logic on the plain object and done.

我很确定有很多更好的方法,请告诉我.

I am quite sure there is a lot better way of doing this, please let me know.

推荐答案

本来可以写出一些东西,但是考虑取回猫鼬对象"似乎是主要考虑因素.

I could have written this out as a few things, but on consideration "getting the mongoose objects back" seems to be the main consideration.

因此,您可以做"各种各样的事情.但是,由于您是将填充引用"填充到对象中,然后想要更改数组中对象的顺序,因此,只有一种方法可以一劳永逸地解决此问题.

So there are various things you "could" do. But since you are "populating references" into an Object and then wanting to alter the order of objects in an array there really is only one way to fix this once and for all.

如果您要按"created_at"的日期对"comments"数组进行排序,那么它甚至可以分解为多种可能性:

If you want your "comments" array sorted by the date they are "created_at" this even breaks down into multiple possibilities:

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

  1. It "should" have been added to in "insertion" order, so the "latest" is last as you note, but you can also "modify" this in recent ( past couple of years now ) versions of MongoDB with $position as a modifier to $push :

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

此操作将数组元素添加"到现有数组的第一个"(0)索引处,因此它始终位于最前面.

This "prepends" the array element to the existing array at the "first" (0) index so it is always at the front.

出于逻辑原因或仅在您希望确定"的地方使用位置"更新失败,因此

Failing using "positional" updates for logical reasons or just where you "want to be sure", then there has been around for an even "longer" time the $sort modifier to $push :

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

这将对数组元素文档的属性进行排序",该属性包含每次修改的指定值.您甚至可以:

And that will "sort" on the property of the array elements documents that contains the specified value on each modification. You can even do:

Article.update(
    {  },
    { 
        "$push": { 
            "comments": { 
                "$each": [], 
                "$sort": { "$created_at": -1 } 
            }
        }
    },
    { "multi": true },
    function(err,result) {
        // other work in here
    }
);

然后按一次命中,将按指定字段对整个集合中的所有评论"数组进行排序.

And that will sort every "comments" array in your entire collection by the specified field in one hit.

使用.aggregate()对数组进行排序和/或在对纯对象执行自己的.sort()之后对猫鼬对象进行重新广播",可以使用其他解决方案.

Other solutions are possible using either .aggregate() to sort the array and/or "re-casting" to mongoose objects after you have done that operation or after doing your own .sort() on the plain object.

这两者实际上都涉及到创建一个单独的模型对象和带有包含引用"信息的嵌入项的模式".因此,您可以在这些行上进行工作,但是当您只需要首先对最需要"的数据进行排序时,这似乎是不必要的开销.

Both of these really involve creating a separate model object and "schema" with the embedded items including the "referenced" information. So you could work upon those lines, but it seems to be unnecessary overhead when you could just sort the data to you "most needed" means in the first place.

另一种方法是确保在调用时通过.toObject()始终将诸如虚拟"之类的字段串行化"为对象格式,并且只保留所有方法现在都已消失并可以使用所示属性的事实.

The alternate is to make sure that fields like "virtuals" always "serialize" into an object format with .toObject() on call and just live with the fact that all the methods are gone now and work with the properties as presented.

最后一个是理智"的方法,但是如果通常使用的是"created_at"顺序,那么在每次操作时都以这种方式存储"数据就更有意义了,因此当您检索"它时,它保持您要使用的顺序.

The last is a "sane" approach, but if what you typically use is "created_at" order, then it makes much more sense to "store" your data that way with every operation so when you "retrieve" it, it stays in the order that you are going to use.

这篇关于猫鼬子文档排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆