【问题标题】:Adding 'virtual' variables to a mongoose schema?将“虚拟”变量添加到猫鼬模式?
【发布时间】:2020-06-08 23:21:48
【问题描述】:

我有以下文档架构:

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

现在,在我的应用程序中,我还希望在对象中包含页面的 html 源代码,但我不想将它存储在数据库中。

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

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

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

【问题讨论】:

  • 为什么要在对象中拥有它而不是存储它?
  • 因为我不需要它是持久的:如果我重新启动服务器并从数据库重新加载对象,该 html 也需要更新(它来自外部进程)。我可以存储它,但它会浪费空间。因为在 Mongoose 中有虚拟方法,所以也有虚拟变量会很好..
  • 您可以简单地在对象上设置 [damn enter] 属性,例如 document.prop = html。如果您再次从数据库中获取对象,我认为该方法或虚拟对象实际上不会让您获取“本地”数据,即使没有重新启动。
  • 哦,对了。我可以简单地添加一个新属性。让我感到困惑的是,如果我执行page.newProperty = "something"; console.log(page),它不会在输出中显示newProperty。但是如果我执行console.log(page.newProperty),我会看到值:|
  • 不要这样做。检查我的答案,猫鼬支持虚拟。

标签: node.js mongoose


【解决方案1】:

这在猫鼬中是完全可能的。
查看此示例,取自他们的文档:

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

在上面的示例中,该属性没有设置器。要为此虚拟设置设置器,请执行以下操作:

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];
});

Documentation

【讨论】:

  • 是的,但他们没有添加新字段。他们正在使用现有字段。
  • 还有什么问题?你也可以使用 setter。
  • 哦,我明白了。你的意思是我应该在虚拟的set 中使用this.newfield =
  • 不确定这是否有意义:l
  • 我必须为模式选项中的“toObject”和“toJSON”激活虚拟。否则它对我不起作用。这里:mongoosejs.com/docs/2.7.x/docs/virtuals.html
【解决方案2】:

__ 开头的文档属性不会保存到数据库中,因此您可以创建一个虚拟属性并让getter 和setter 使用this.__html

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

但这有点像一个 hack 有一个警告:这个功能没有记录,所以没有以 __ 开头的内部属性列表,所以有可能,尽管不太可能,在未来内部实现可以开始使用一个名为__html的变量

https://github.com/Automattic/mongoose/issues/2642

【讨论】:

    【解决方案3】:

    我还没有实际测试过,但这个想法似乎值得:

    //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 的虚拟属性输出。

    pageSchema.set('toJSON', {
        virtuals: true
    });
    

    【讨论】:

      【解决方案4】:

      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)
      });
      

      【讨论】:

        猜你喜欢
        • 2013-09-13
        • 2023-04-07
        • 2021-01-09
        • 1970-01-01
        • 2014-04-01
        • 2017-04-22
        • 2017-04-04
        相关资源
        最近更新 更多