上下文是什么:“查询”选项使用mongoose时做什么?

在一个 失败的尝试 学习练习让validation器与“document.update”一起工作,我遇到了一些我不明白的东西。

我现在知道这是行不通的,但我尝试的一个方法是将我的选项设置为{runValidators:true,context:'query'}。 在我的validation器function,我试着console.logging(这个),有和没有上下文:“查询”选项。

没有区别。 我收到一个大的对象(这叫做“查询对象”?)这似乎违背了我在这里阅读的内容。

在上面的颜色validationfunction中,这是指在使用文档validation时正在validation的文档。 但是,在运行更新validation程序时,正在更新的文档可能不在服务器的内存中,所以默认情况下这个值没有被定义。

没有定义,即使没有上下文选项。

我甚至试图把它作为一个箭头函数,看看这个词汇是否有什么不同。 在这种情况下,这不确定的,但是再次改变上下文选项并没有什么不同。 (我还在学习,所以我不知道这部分是否相关)。

在模型中:

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){ 

任何事情,以帮助我更好地理解我认为我正在阅读和我所看到的将是伟大的差异!

首先,我们要明确validation器有两种types:文档validation器和更新validation器(也许您已经知道这一点,但是您发布的代码片段会更新文档,因为您提到的问题是文档validation)。

没有区别。 我收到一个大的对象(这叫做“查询对象”?)这似乎违背了我在这里阅读的内容。

如文档中所述,运行文档save时将运行文档validation程序。

validation是中间件。 Mongoose默认将validation注册为每个模式的预('保存')钩子。

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

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

更新validation器运行更新操作

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

这可以用下面的代码片段来说明。 为了方便起见,我已经将tenants的types改为了一个简单的整型数组,但是这对我们讨论的目的应该是重要的。

 // "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(); }); 

以上代码触发更新validation而不是文档validation

要在操作中查看文档validation,请取消注释property.save()并注释更新操作。

你会注意到这个值将是property文件。

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

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

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

这可以用mongoose来源的这条线来解释。 当没有设置上下文时,mongoose把范围设置为null 。 然后在这里调用scope .call

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

希望这有助于你更好地理解事物。