簡體   English   中英

在 mongoDB (mongoose) 中按虛擬字段排序

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

假設我有一些 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;
});

在查詢中是否可以按虛擬字段對結果進行排序? 就像是

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

當我嘗試這個時,結果很簡單,沒有排序......

您將無法按虛擬字段排序,因為它們未存儲到數據庫中。

虛擬屬性是便於使用但不會持久保存到mongodb的屬性。

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

我不知道在聚合中重用現有虛擬的任何方法,但您可能能夠在聚合階段將虛擬投影到您的文檔中。

我抽象了我最近構建的聚合管道。 想象一下,您有一組鍵,其中包含一組直接存儲在團隊文檔中的玩家。 下面的管道將按照優先球員的排名對這些球隊進行排序,其中優先球員基本上是一個虛擬財產,在某些情況下包含球隊中最相關的球員(在這個例子中,我們只想考慮進攻和防守球員)。 在我們的案例中,這種情況有多種可能性,取決於用戶的選擇,因此無法在文檔中持久化。

我們的“團隊”文檔非常大,並且由於投影文檔僅在內存中可用,如果我們只添加一個字段並將團隊集合的整個文檔保存在內存中,那么它會帶來巨大的性能成本。 因此我們只投影我們需要的那些字段,在限制結果后進行排序和恢復原始文檔。

[
  // 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