Node.js 添加';虚拟';mongoose模式的变量?

Node.js 添加';虚拟';mongoose模式的变量?,node.js,mongoose,Node.js,Mongoose,我有以下文档架构: var pageSchema = new Schema({ name: String , desc: String , url: String }) 现在,在我的应用程序中,我还希望在对象中包含页面的html源代码,但我不希望将其存储在db中 我应该创建一个引用db文档的“本地”增强对象吗 function Page (docModel, html) { this._docModel = docModel this._html =

我有以下文档架构:

var pageSchema = new Schema({
      name: String
    , desc: String
    , url: String
})
现在,在我的应用程序中,我还希望在对象中包含页面的html源代码,但我不希望将其存储在db中

我应该创建一个引用db文档的“本地”增强对象吗

function Page (docModel, html) {
    this._docModel = docModel
    this._html = html
}

有没有办法通过添加“虚拟”字段直接使用文档模型?

这在mongoose中是完全可能的。
从他们的文档中选取以下示例:

var personSchema = new Schema({
  name: {
    first: String,
    last: String
  }
});

personSchema.virtual('name.full').get(function () {
  return this.name.first + ' ' + this.name.last;
});
console.log('%s is insane', bad.name.full); // Walter White is insane
在上面的示例中,属性没有setter。要为此虚拟机设置setter,请执行以下操作:

personSchema.virtual('name.full').get(function () {
  return this.name.full;
}).set(function(name) {
  var split = name.split(' ');
  this.name.first = split[0];
  this.name.last = split[1];
});

我还没有实际测试过这一点,但这个想法似乎很有价值:

//model
var pageSchema = new Schema({
      name: String
    , desc: String
    , url: String
})

pageSchema.virtual('html')
  .get(function(){
    var url = this.url

    function get(url) {
      return new (require('httpclient').HttpClient)({
        method: 'GET',
          url: url
        }).finish().body.read().decodeToString();
    }

    return get(url);
  });


  //controller
  var page = new Page({
    name: "Google"
    , desc: "Search engine"
    , url: "http://google.com"
  });

  var html = page.html;
基本上设置一个名为
html
的虚拟属性,该属性请求
url
属性的主体并返回它

如果您正在使用express和
res.send(page)
,请确保为toJSON启用虚拟属性的输出


开头的文档属性不会持久化到数据库中,因此您可以创建一个虚拟属性,并让getter和setter使用
。\uu html

pageSchema.virtual('html').get(function () {
  return this.__html;
}).set(function (html) {
  this.__html = html;
});
但这有点像黑客攻击,但有一点需要注意:此功能没有文档记录,因此没有以
\uuuu
开头的内部属性列表,因此有可能(尽管可能性不大)在将来内部实现可以开始使用名为
\uuu html
的变量

pageSchema.virtual('html').get(function () {
  return this.__html;
}).set(function (html) {
  this.__html = html;
});

2020年

可以通过在模型中添加以下对象字段来设置虚拟对象

toJSON: { virtuals: true },
toObject: { virtuals: true }
上面的例子和下面的例子是等价的,但上面的例子简短而简单

itemSchema.set('toJSON', {
    virtuals: true
});
这是一个例子 型号

const itemsSchema = new mongoose.Schema({
    image: {
        type: String,
        trim: true,
        required: [true, 'Please provide item image']
    },
    color: {
        type: String,
        trim: true
    },
    size: {
        type: String,
        trim: true
    },
    price: {
        type: Number,
        required: [true, 'Please provide item price']
    },
    shipping: {
        type: Number
    },
    discount: {
        type: Number
    },
    details: {
        type: String,
        trim: true
    }
}, {
    toJSON: { virtuals: true },
    toObject: { virtuals: true }
});
设置虚拟模式

itemsSchema.virtual('totalPrice').get(function() {
    const sub_total = this.price + this.shipping;
    return (sub_total - ( ( sub_total / 100 ) * this.discount )).toFixed(2)
});

为什么要将它放在对象中而不是存储它?因为我不需要它是持久的:如果我重新启动服务器并从数据库中重新加载对象,html也需要更新(它来自外部进程)。我可以储存它,但这会浪费空间。因为在Mongoose中有虚拟方法,所以最好也有虚拟变量。您只需在对象上设置一个属性,如
document.prop=html
。我认为,如果您再次从数据库中获取对象,即使不重新启动,该方法或virtuals实际上也不会让您获取“本地”数据。哦,对了。我可以简单地添加一个新属性。让我困惑的是,如果我做了
page.newProperty=“something”;console.log(page)
它不会在输出中显示
newProperty
。。但是如果我做了
console.log(page.newProperty)
我会看到值:|不要这样做。检查我的答案,mongoose支持虚拟现实。是的,但他们没有添加新字段。。他们正在使用现有的。问题是什么?你也可以使用setter。哦,我明白了。你的意思是我应该
this.newfield=
在虚拟
set
中。但我不确定这是否有任何意义:lI必须在模式选项中为“toObject”和“toJSON”激活虚拟体。否则我就不行了。在这里: