如何在mongoose模式中拥有自动计算的属性

tsm1rwdh  于 2023-10-19  发布在  Go
关注(0)|答案(5)|浏览(93)

假设我在Node.js中有以下mongoose模式

var schema = new mongoose.Schema({
    views:Number,
    clicks:Number,
    ctr:Number
})

在其中,我希望CTR属性应该根据其他属性的值自动计算公式,即让我们说

ctr =点击次数/浏览次数

我不想把CTR作为一个虚拟字段,因为基于CTR的值,我将对我收藏的所有文档进行排序,显然基于虚拟字段进行排序是不可能的。因此,我想知道是否有任何方法可以在mongoose模式中计算属性,并在更新任何依赖属性/字段时自动更新

hts6caw3

hts6caw31#

我想CTR属性应该是自动计算的公式的基础上的其他属性的值
Mongoose docs [强调添加]:

**您也可以将default schema选项设置为函数。**Mongoose将执行该函数并使用返回值作为默认值。

因此,您的示例可以重写为:

const schema = new mongoose.Schema({
  views: {
    type: Number
  },
  clicks: {
    type: Number
  },
  ctr: {
    type: Number,
    default: function() {
      return this.clicks / this.views
    }
  }
})

因此,我想知道是否有任何方法可以在mongoose模式中计算属性,并在更新任何依赖属性/字段时自动更新
如果我理解正确的话,请注意文档中关于setDefaultsOnInsert选项的部分。这可能与更新时重新计算默认值有关。

w9apscun

w9apscun2#

您可以使用它的虚拟字段:

var schema = new mongoose.Schema({
    views:Number,
    clicks:Number
})

schema.virtual('ctr')
  .get(function() {
    return this.clicks / this.views;
  });
kuhbmx9i

kuhbmx9i3#

你可以做任何事情,但不要忘记那件困难的事情会让你的服务器变慢。
在我的情况下,计算年龄的用户,我这样做。

const mongoose = require( 'mongoose' );
const Schema = mongoose.Schema;

    const userSchema = new Schema( {

      born: {
        type: String,
        get: a => {
          let date = new Date(a);
          let today = new Date();
          let timeDiff = today.getTime() - date.getTime();
          let age = Math.floor( timeDiff / ( 1000 * 3600 * 24 ) / 365 );
          return age;
        },
        set: age => age,
        alias: 'age',
      },
    } 

);

module.exports = mongoose.model( 'User', userSchema );

Mongoose Documantation

mwngjboj

mwngjboj4#

另一种方法是使用预保存中间件。我正在我的Schema中实现它,到目前为止它工作得很好。不过,需要注意的是,它不会因更新而触发。格式如下:

schema
  .pre('save', function(next){
   this.ctr = this.clicks/this.views
   next();   
});
lx0bsm1f

lx0bsm1f5#

另一种方式,从这篇文章Mongoose pre hooks for save and update do not get called when i used a Model.findOneAndUpdate的最高评分答案中得出:

yourSchema.post("findOneAndUpdate", async function() {
  const docToUpdate = await this.model.findOne(this.getQuery());
  // do your calculations
  // await docToUpdate.ctr = docToUpdate.clicks/docToUpdate.views
  await docToUpdate.save();
});

相关问题