如何在猫鼬模式中有一个自动计算的属性

Poi*_*rks 8 mongoose mongodb node.js

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

var schema = new mongoose.Schema({
    views:Number,
    clicks:Number,
    ctr:Number
})
Run Code Online (Sandbox Code Playgroud)

我希望 CTR 属性应该由基于其他属性值的公式自动计算,即让我们说

ctr = 点击次数/观看次数

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

小智 12

我希望 CTR 属性应该由基于其他属性值的公式自动计算

来自猫鼬文档[强调添加]:

您还可以将默认架构选项设置为函数。Mongoose 将执行该函数并使用返回值作为默认值。

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

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

所以我想知道是否有任何方法可以在 mongoose 模式中计算属性,该模式会在更新任何依赖属性/字段时自动更新

如果我理解正确,请注意setDefaultsOnInsert选项文档中的部分。在更新时重新计算默认值时,这可能是相关的。


小智 7

您可以使用它虚拟字段:

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

schema.virtual('ctr')
  .get(function() {
    return this.clicks / this.views;
  });
Run Code Online (Sandbox Code Playgroud)

  • 感谢@Sergaros 花时间回答我的问题,但正如我在问题中提到的,我不想将 CTR 作为虚拟字段,因为根据 CTR 的值,我将对我收藏的所有文档进行排序,显然排序是不可能的基于虚拟字段。所以我想知道是否有任何方法可以在 mongoose 模式中计算属性,该模式会在更新任何依赖属性/字段时自动更新 (2认同)

小智 7

你可以做任何事情,但不要忘记让你的服务器变慢的困难。

在我计算用户年龄的例子中,我就是这样做的。

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

Mongoose 文档