上下文是什么:'query'选项在使用mongoose时会怎么做?

Mat*_*tch 11 javascript validation mongoose mongodb node.js

在一个 尝试失败 学习练习让验证者使用'document.update',我遇到了一些我不理解的东西.

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

没有区别.我收到一个大对象(这被称为'查询对象'?)这似乎违背了我在这里读到的内容.

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

即使没有上下文选项,它也没有未定义.

我甚至尝试使它成为一个箭头函数,看看这个词汇是否有所不同.在这种情况下,这未定义的,但同样,更改上下文选项并没有什么不同.(我还在学习,所以我不知道那部分是否相关).

在模型中:

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

并在路线:

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

有什么可以帮助我更好地理解我认为我正在阅读的东西和我看到的东西之间的差异会很棒!

Man*_*nth 5

首先,让我们清楚验证器有两种类型:文档验证器和更新验证器(也许你已经知道了,但你发布的代码片段更新了一个文档,你提到的问题是文档验证).

没有区别.我收到一个大对象(这被称为'查询对象'?)这似乎违背了我在这里读到的内容.

当您运行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();
});
Run Code Online (Sandbox Code Playgroud)

上面的代码触发更新验证而不是文档验证

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

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

this { name: 'foo',
occupancy: 'bar',
_id: 598e9d72992907120a99a367,
tenants: [ 1 ] }
Run Code Online (Sandbox Code Playgroud)

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

现在,您可能没有意识到的大对象是未设置的全局对象,context: 'query'以及设置上下文时的查询对象.

这可以在解释这条线在猫鼬的来源.如果未设置上下文,则mongoose将范围设置为null.然后这里.call被调用的scope.

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

希望这有助于您更好地理解事物.