簡體   English   中英

MongoDB Aggregate 中的 Mongoose Virtuals

[英]Mongoose Virtuals in MongoDB Aggregate

我的貓鼬模式如下:

var DSchema = new mongoose.Schema({
  original_y: {type: Number},,
  new_y: {type: Number},,
  date: {type: Date},
  dummy: [dummyEmbeddedDocuments]
  }, toObject: { virtuals: true }, toJSON: { virtuals: true}
});

DSchema.virtual('dateformatted').get(function () {
 return moment(this.date).format('YYYY-MM-DD HH:mm:ss');
});

module.exports = mongoose.model('D', DSchema);

我的架構中的文檔如下:

{
 id:1,
 original_y: 200,
 new_y: 140,
 date: 2015-05-03 00:00:00.000-18:30,
 dummy: [
  {id:1, storage:2, cost: 10},
  {id:2, storage:0, cost: 20},
  {id:3, storage:5, cost: 30},
  ]
}

我的查詢:

Item.aggregate([
{ 
    "$match": {
        "dummy.storage": {"$gt": 0}
    } 
},
{ 
    "$unwind": "$dummy"
},
{
    "$project": {
        "original_y": 1, 
        "new_y": 1,
        "dateformatted": 1,
        "dummy.id": "$dummy.id",
        "dummy.storage": "$dummy.storage",
        "dummy.cost": "$dummy.cost",
        "dummy.tallyAmount": {
            "$divide": [
                { "$add": ["$new_y","$original_y"] },
                "$dummy.cost"
            ]
        }
    }
},
{
    "$group": {
        "_id": "_$id",
        "original_y": { "$first": "$original_y" },
        "dateformatted": { "$first": "$dateformatted" },
        "new_y": { "$first": "$new_y" },
        "dummy": {
            "$addToSet": "$dummy"
        }
    }        
}
]).exec(callback);

但是,此查詢將VIRTUAL dateformatted 屬性返回為 NULL。 關於為什么會發生這種情況的任何想法?

文檔中的一些注釋觸及了為什么會這樣:

  • 參數不會轉換為模型的模式,因為$project運算符允許在管道的任何階段重新定義文檔的“形狀”,這可能會使文檔格式不兼容。
  • 返回的文檔是純 javascript 對象,而不是貓鼬文檔(因為可以返回任何形狀的文檔)。

但它超越了這一點,因為aggregate操作是在服務器端執行的,其中不存在任何客戶端 Mongoose 概念,如虛擬。

結果是您需要在$project$group階段中包含date字段,並根據date值將您自己的dateformatted字段添加到代碼中的結果中。

這是一個老問題,但我想出了一個有用的技巧來找回虛擬機,並認為它可能對那些尋找這個問題的人有用。

您可以輕松地將對象轉換回貓鼬模型:

documents = documents.map(d => {
  return new Document(d);
});

var virtual = documents[0].virtualProperty;

<field>: <1 or true>表單用於包含一個現有字段,這里不是這種情況,因為dateformatted字段不存在,您必須使用表達式創建它,可以使用$dateToString

"$project": {
  "original_y": 1, 
  "new_y": 1,
  "dateformatted": { "$dateToString": { "format": "%Y-%m-%d %H:%M:%S", "date": "$date" } },
  ...

另一種選擇是將其與$addFields一起使用:

{
  "$project": {
    ...
  }
},
{
  "$addFields": {
    "dateformatted": { "$dateToString": {"format": "%Y-%m-%d %H:%M:%S", "date": "$date"} }
  }
},
...

這是一個有效的解決方案! 聚合查詢返回不是 mongoose Document 實例的 js 對象。 您可以使用Model.hydrate

const documents = docs.map(doc => myModel.hydrate(doc))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM