繁体   English   中英

使用 mongoose 时 context:'query' 选项有什么作用?

[英]What does the context:'query' option do when using mongoose?

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

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

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

在上面的颜色验证功能中,这是指使用文档验证时正在验证的文档。 但是,在运行更新验证器时,正在更新的文档可能不在服务器的内存中,因此默认情况下未定义 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){

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

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

没有区别。 我收到了一个大对象(这是否称为“查询对象”?)这似乎与我在这里读到的内容相反。

如文档中所述,当您对文档运行save时,将运行文档验证器。

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

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

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

更新验证器用于更新操作

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

这可以用以下代码段说明。 为方便起见,我已将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()并注释更新操作。

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM