【问题标题】:What does the context:'query' option do when using mongoose?使用 mongoose 时 context:'query' 选项有什么作用?
【发布时间】:2016-11-02 04:44:33
【问题描述】:

失败的尝试让验证器使用“document.update”的学习练习中,我遇到了一些我不明白的东西。

我现在知道它不起作用,但我尝试的其中一件事是将我的选项设置为 {runValidators:true, context:'query'}。在我的验证器函数中,我尝试了 console.logging (this),有和没有 context:"query" 选项。

没有区别。我收到了一个大对象(这是否称为“查询对象”?)这似乎与我阅读的 here 背道而驰。

在上面的颜色验证功能中,这是指使用文档验证时正在验证的文档。但是,在运行更新验证器时,正在更新的文档可能不在服务器的内存中,因此默认情况下 this 的值没有定义。

它不是 undefined ,即使没有上下文选项。

我什至尝试将其设为箭头函数,以查看词汇 this 是否有任何不同。在这种情况下,这个 是未定义的,但同样,更改上下文选项并没有什么不同。 (我还在学习,所以我不知道那部分是否相关)。

在模型中:

let Property = mongoose.model('Property', {
    name: {type:String, required:true},
    occupancy: {type:String},
    maxTenants: Number,
    tenants: [{ type:mongoose.Schema.Types.ObjectId, ref: 'Tenant', validate: [checkMaxTenants, "Maximum tenants exceeded for this property. Tenant not added."]}]
});
function checkMaxTenants(val){
    console.log("this",this);
    // return this.tenants.length <= this.maxTenants;
    return true;
}

在路线中:

        property.update({$set: {tenants:property.tenants}},{new:true,runValidators:true,context:'query'}, function(err,savedProperty){

任何能帮助我更好地理解我认为我正在阅读的内容与我看到的内容之间的差异的东西都会很棒!

【问题讨论】:

    标签: javascript node.js mongodb validation mongoose


    【解决方案1】:

    首先,让我们明确验证器有两种类型:文档验证器和更新验证器(也许您已经知道这一点,但是您发布的 sn-p 更新文档,而问题您提到的与save 上的文档验证有关。

    没有区别。我收到了一个大对象(这是否称为“查询对象”?)这似乎与我在此处阅读的内容背道而驰。

    文档验证器在您对文档中提到的文档运行 save 时运行。

    验证是中间件。默认情况下,Mongoose 将验证注册为每个模式的 pre('save') 挂钩。

    或者您可以使用.validate()手动调用它

    您可以使用 doc.validate(callback) 或 doc.validateSync() 手动运行验证

    为更新操作运行更新验证器

    在上述示例中,您了解了文档验证。 Mongoose 还支持对 update() 和 findOneAndUpdate() 操作的验证。

    这可以用下面的 sn-p 来说明。为方便起见,我已将 tenants 的类型更改为简单的整数数组,但这对于我们的讨论目的而言无关紧要。

    // "use strict";
    
    const mongoose = require('mongoose');
    const assert = require('assert');
    const Schema = mongoose.Schema;
    
    let Property = mongoose.model('Property', {
      name: { type: String, required: true },
      occupancy: { type:String },
      maxTenants: Number,
      tenants: [
        {
          type: Number,
          ref: 'Tenant',
          validate: {
            validator: checkMaxTenants,
            message: "Maximum tenants exceeded for this property. Tenant not added."
          }
        }
      ]
    });
    
    function checkMaxTenants (val) {
      console.log("this", this);
      // return this.tenants.length <= this.maxTenants;
      return true;
    }
    
    mongoose.Promise = global.Promise;
    mongoose.createConnection('mongodb://localhost/myapp', {
      useMongoClient: true,
    }).then(function(db) {
    
      const property = new Property({ name: 'foo', occupancy: 'bar', tenants: [1] });
    
      property.update(
        { $set: { tenants: [2, 3] } },
        {
          new: true,
          runValidators: true,
          // context: 'query'
        },
        function(err, savedProperty) {
    
        }
      )
    
      // property.save();
    });
    

    以上代码触发更新验证不是文档验证

    要查看正在执行的文档验证,请取消注释 property.save() 并注释更新操作。

    您会注意到它的值将是property 文档。

    this { name: 'foo',
    occupancy: 'bar',
    _id: 598e9d72992907120a99a367,
    tenants: [ 1 ] }
    

    注释保存,取消注释更新操作,你会看到你提到的大对象。

    现在你得到的大对象,你可能没有意识到,是你没有设置context: 'query'时的全局对象和你设置上下文时的查询对象。

    这可以在猫鼬源中的this line 进行解释。当没有设置上下文时,猫鼬将范围设置为null。然后here .callscope 调用。

    现在,在非严格模式下,当 .call 以 null 调用时,this is replaced with the global object。所以检查你得到的大对象的内容。当context 未设置时,它将是一个全局对象而不是查询对象。您可以添加 "use strict"; 并查看将记录 null。 (发布的 sn-p 可以为您验证这一点)。您可以通过对 this 运行 instanceof mongoose.Query 来验证您是否获得了查询对象。

    希望这可以帮助您更好地理解事物。

    【讨论】:

    • 我们不能使用相同的验证器来保存和更新,因为这个值在两个用例中都在变化
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-18
    • 2016-11-02
    • 2015-10-11
    • 1970-01-01
    • 2012-02-17
    相关资源
    最近更新 更多