MongoDB聚合中的Mongoose虚拟

Roh*_*ala 6 mongoose mongodb node.js aggregation-framework

我的猫鼬模式如下:

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);
Run Code Online (Sandbox Code Playgroud)

我的架构中的文档如下:

{
 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},
  ]
}
Run Code Online (Sandbox Code Playgroud)

我的查询:

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);
Run Code Online (Sandbox Code Playgroud)

但是,此查询返回的虚拟日期格式属性为NULL。为什么会这样呢?

ben*_*ear 9

这是一个老问题,但我想出了一个有用的技巧来恢复虚拟,并认为它可能对那些寻找这个问题的人有用。

您可以轻松地将对象转换回猫鼬模型:

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

var virtual = documents[0].virtualProperty;
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!我对其进行了轻微修改,通过调用“.toJSON()”来填充虚拟值。`documents.map(d => new Document(d).toJSON())` (3认同)

Joh*_*yHK 6

文档中有一些注释说明为什么会这样:

  • 参数不会转换为模型的架构,因为$project运算符允许在管道的任何阶段重新定义文档的“形状”,这可能会使文档的格式不兼容。
  • 返回的文档是纯JavaScript对象,不是猫鼬文档(因为可以返回任何形状的文档)。

但这还不止于此,因为该aggregate操作是在服务器端执行的,在该服务器端,不存在任何客户端Mongoose概念(例如虚拟)。

结果是您需要date$project$group阶段中包含该字段,然后dateformatted根据date值将自己的字段添加到代码中的结果中。

  • `返回的文档是纯javascript对象`这是否意味着我不能对聚合框架查询返回的文档使用虚拟字段和猫鼬的方法? (2认同)