简体   繁体   English

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

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

In a在一个failed attempt失败的尝试learning exercise to get validators to work with 'document.update', I came across something I don't understand.学习练习让验证器使用“document.update”,我遇到了一些我不明白的事情。

I know now that it doesn't work, but one of the things I tried was setting my options to {runValidators:true, context:'query'}.我现在知道它不起作用,但我尝试过的一件事是将我的选项设置为 {runValidators:true, context:'query'}。 In my validator function, I tried console.logging (this), with and without the context:"query" option.在我的验证器函数中,我尝试了 console.logging (this),有和没有 context:"query" 选项。

There was no difference.没有区别。 I received a large object (is this called the 'query object'?) This seems to go against what I read here .我收到了一个大对象(这是否称为“查询对象”?)这似乎与我在此处阅读的内容相悖

In the color validation function above, this refers to the document being validated when using document validation.在上面的颜色验证功能中,这是指使用文档验证时正在验证的文档。 However, when running update validators, the document being updated may not be in the server's memory, so by default the value of this is not defined.但是,在运行更新验证器时,正在更新的文档可能不在服务器的内存中,因此默认情况下未定义 this 的值。

It was not undefined , even without the context option.即使没有上下文选项,它也不是 undefined 。

I even tried making it an arrow function to see if the lexical this was any different.我什至尝试将其设为箭头函数,以查看词法 this 是否有任何不同。 In that case, this was undefined, but again, changing the context option did not make a difference.在那种情况下,这未定义的,但同样,更改上下文选项没有任何区别。 (I'm still learning, so I don't know if that part is relevant). (我还在学习,所以我不知道那部分是否相关)。

in the model:在模型中:

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;
}

and in the route:并在路线中:

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

Anything to help me better understand the discrepancy between what I think I'm reading and what I see would be great!任何能帮助我更好地理解我认为我正在阅读的内容与我所看到的内容之间的差异的东西都会很棒!

At the outset, let's be clear that validators are of two types: document validators and update validators (maybe you know this already, but the snippet you posted updates a document, whereas the issue you mention relates to document validation upon save ).首先,让我们明确验证器有两种类型:文档验证器和更新验证器(也许您已经知道这一点,但是您发布的代码段更新了文档,而您提到的问题与save文档验证有关)。

There was no difference.没有区别。 I received a large object (is this called the 'query object'?) This seems to go against what I read here.我收到了一个大对象(这是否称为“查询对象”?)这似乎与我在这里读到的内容相反。

Document validators are run when you run save on documents as mentioned in the docs.如文档中所述,当您对文档运行save时,将运行文档验证器。

Validation is middleware.验证是中间件。 Mongoose registers validation as a pre('save') hook on every schema by default.默认情况下,Mongoose 将验证注册为每个模式上的 pre('save') 钩子。

Or you can call it manually with .validate()或者您可以使用.validate()手动调用它

You can manually run validation using doc.validate(callback) or doc.validateSync()您可以使用 doc.validate(callback) 或 doc.validateSync() 手动运行验证

Update validators are run for update operations更新验证器用于更新操作

In the above examples, you learned about document validation.在上面的示例中,您了解了文档验证。 Mongoose also supports validation for update() and findOneAndUpdate() operations. Mongoose 还支持对 update() 和 findOneAndUpdate() 操作的验证。

This can be illustrated with the following snippet.这可以用以下代码段说明。 For convenience I have changed the type of tenants to a simple integer array, but that shouldn't matter for the purpose of our discussion.为方便起见,我已将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();
});

Above code with trigger a update validation not document validation上面的代码触发更新验证而不是文档验证

To see document validation in action uncomment property.save() and comment the update operation.要查看操作中的文档验证,请取消注释property.save()并注释更新操作。

You'll notice that the value of this will be the property document.您会注意到 this 的值将是property文档。

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

Comment the save, uncomment back the update operation and you'll see the large object you mentioned.注释保存,取消注释更新操作,您将看到您提到的大对象。

Now the large object you got, you may not have realised, is the global object when you didn't set context: 'query' and the query object when you set the context.现在你得到的大对象,你可能没有意识到,是你没有设置context: 'query'时的全局对象context: 'query'和你设置上下文时的查询对象。

This can be explained at this line in mongoose's source.这可以在猫鼬来源的这一行中解释。 When no context was set, mongoose sets the scope to null .当没有设置上下文时,mongoose 将范围设置为null And then here the .call is called with the scope .然后这里.callscope调用。

Now, in non strict mode, when .call is called with null, this is replaced with the global object .现在,在非严格模式下,当.call用 null 调用时, this被替换为全局对象 So check contents of the large object you got.所以检查你得到的大对象的内容。 When context is not set, it would be a global object and not the query object.context未设置时,它将是一个全局对象而不是查询对象。 You can add "use strict";您可以添加"use strict"; and see that null will be logged.并看到将记录空值。 (The snippet posted can verify this for you). (发布的片段可以为您验证这一点)。 You can verify that you got a query object by running instanceof mongoose.Query against this .您可以通过对this运行 instanceof mongoose.Query来验证您是否获得了查询对象。

Hope this helps you understand things better.希望这可以帮助您更好地理解事物。

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

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