简体   繁体   English

在 mongoDB (mongoose) 中按虚拟字段排序

[英]Sorting by virtual field in mongoDB (mongoose)

Let's say I have some Schema which has a virtual field like this假设我有一些 Schema,它有一个像这样的虚拟字段

var schema = new mongoose.Schema(
{
    name: { type: String }
},
{
    toObject: { virtuals: true },
    toJSON: { virtuals: true }
});

schema.virtual("name_length").get(function(){
    return this.name.length;
});

In a query is it possible to sort the results by the virtual field?在查询中是否可以按虚拟字段对结果进行排序? Something like就像是

schema.find().sort("name_length").limit(5).exec(function(docs){ ... });

When I try this, the results are simple not sorted...当我尝试这个时,结果很简单,没有排序......

You won't be able to sort by a virtual field because they are not stored to the database. 您将无法按虚拟字段排序,因为它们未存储到数据库中。

Virtual attributes are attributes that are convenient to have around but that do not get persisted to mongodb. 虚拟属性是便于使用但不会持久保存到mongodb的属性。

http://mongoosejs.com/docs/2.7.x/docs/virtuals.html http://mongoosejs.com/docs/2.7.x/docs/virtuals.html

I don't know about any ways to reuse existing virtuals in aggregations but you might be able to project virtuals to your documents in aggregation stages.我不知道在聚合中重用现有虚拟的任何方法,但您可能能够在聚合阶段将虚拟投影到您的文档中。

I abstracted an aggregation pipeline I recently build.我抽象了我最近构建的聚合管道。 Imagine you have a collection of keys with an array of players directly stored in the team document.想象一下,您有一组键,其中包含一组直接存储在团队文档中的玩家。 The following pipeline would sort those teams by the ranking of the favoredPlayer where the favoredPlayer is basically a virtual property containing the most relevant player of the team under certain circumstances (in the example we only want to consider offense and defense players).下面的管道将按照优先球员的排名对这些球队进行排序,其中优先球员基本上是一个虚拟财产,在某些情况下包含球队中最相关的球员(在这个例子中,我们只想考虑进攻和防守球员)。 This circumstances in our case have a variety of possibilities and are depending on the users choices and can therefore not be persisted on the document.在我们的案例中,这种情况有多种可能性,取决于用户的选择,因此无法在文档中持久化。

Our "team" document is pretty large and since projected documents are only available in memory it would come with a huge performance cost if we just add a field and have the whole documents of the teams collection in memory.我们的“团队”文档非常大,并且由于投影文档仅在内存中可用,如果我们只添加一个字段并将团队集合的整个文档保存在内存中,那么它会带来巨大的性能成本。 Therefore we project only those fields we need for sorting and restore the original document after limiting the results.因此我们只投影我们需要的那些字段,在限制结果后进行排序和恢复原始文档。

[
  // find all teams from germany
  { '$match': { country: 'de' } },
  // project to documents containing sort relevant fields
  // and add field favoredPlayer per team
  { '$project': {
    rank: 1,
    'favoredPlayer': {
      '$arrayElemAt': [
        {
          // remove players that should be ignored
          $filter: {
            input: '$players',
            as: 'p',
            cond: { $in: ['$$p.position', ['offense', 'defense']] },
          },
        },
        // take first of the filtered players since players are already sorted by relevance in our db
        0,
      ],
    },
  }},
  // sort teams by the ranking of the favoredPlayer
  { '$sort': { 'favoredPlayer.ranking': -1, rank: -1 } },
  { '$limit': 10 },
  // $lookup $unwind $replaceRoot to restore original database document
  { '$lookup': { from: 'teams', localField: '_id', foreignField: '_id', as: 'subdoc' } },
  { '$unwind': { path: '$subdoc' } },
  { '$replaceRoot': { newRoot: '$subdoc' } },
];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM