Query Casting查询铸造

The first parameter to Model.find(), Query#find(), Model.findOne(), etc. is called filter. In older content this parameter is sometimes called query or conditions. Model.find()Query#find()Model.findOne()等的第一个参数称为filter。在较旧的内容中,此参数有时被称为queryconditionsFor example:例如:

const query = Character.find({ name: 'Jean-Luc Picard' });
query.getFilter(); // `{ name: 'Jean-Luc Picard' }`

// Subsequent chained calls merge new properties into the filter
query.find({ age: { $gt: 50 } });
query.getFilter(); // `{ name: 'Jean-Luc Picard', age: { $gt: 50 } }`

When you execute the query using Query#exec() or Query#then(), Mongoose casts the filter to match your schema.当您使用Query#exec()Query#then()执行查询时,Mongoose会强制转换筛选器以匹配您的模式。

// Note that `_id` and `age` are strings. Mongoose will cast `_id` to
// a MongoDB ObjectId and `age.$gt` to a number.
const query = Character.findOne({
_id: '5cdc267dd56b5662b7b7cc0c',
age: { $gt: '50' }
});

// `{ _id: '5cdc267dd56b5662b7b7cc0c', age: { $gt: '50' } }`
// Query hasn't been executed yet, so Mongoose hasn't casted the filter.
query.getFilter();

const doc = await query.exec();
doc.name; // "Jean-Luc Picard"

// Mongoose casted the filter, so `_id` became an ObjectId and `age.$gt`
// became a number.
query.getFilter()._id instanceof mongoose.Types.ObjectId; // true
typeof query.getFilter().age.$gt === 'number'; // true

If Mongoose fails to cast the filter to your schema, your query will throw a CastError.如果Mongoose未能将筛选器强制转换为您的模式,那么您的查询将抛出一个CastError

const query = Character.findOne({ age: { $lt: 'not a number' } });

const err = await query.exec().then(() => null, err => err);
err instanceof mongoose.CastError; // true
// Cast to number failed for value "not a number" at path "age" for model "Character"对于模型“Character”的路径“age”处的值“非数字”,强制转换为数字失败
err.message;

The strictQuery OptionstrictQuery选项

By default, Mongoose does not cast filter properties that aren't in your schema.默认情况下,Mongoose不会强制转换不在您的模式中的筛选器属性。

const query = Character.findOne({ notInSchema: { $lt: 'not a number' } });

// No error because `notInSchema` is not defined in the schema
await query.exec();

You can configure this behavior using the strictQuery option for schemas. 您可以使用模式的strictQuery选项来配置此行为。This option is analogous to the strict option. Setting strictQuery to true removes non-schema properties from the filter:此选项类似于strict选项。将strictQuery设置为true将从筛选器中删除非架构属性:

mongoose.deleteModel('Character');
const schema = new mongoose.Schema({ name: String, age: Number }, {
strictQuery: true
});
Character = mongoose.model('Character', schema);

const query = Character.findOne({ notInSchema: { $lt: 'not a number' } });

await query.exec();
query.getFilter(); // Empty object `{}`, Mongoose removes `notInSchema`

To make Mongoose throw an error if your filter has a property that isn't in the schema, set strictQuery to 'throw':如果filter的属性不在架构中,要使Mongoose抛出错误,请将strictQuery设置为'throw'

mongoose.deleteModel('Character');
const schema = new mongoose.Schema({ name: String, age: Number }, {
strictQuery: 'throw'
});
Character = mongoose.model('Character', schema);

const query = Character.findOne({ notInSchema: { $lt: 'not a number' } });

const err = await query.exec().then(() => null, err => err);
err.name; // 'StrictModeError'
// Path "notInSchema" is not in schema and strictQuery is 'throw'.
err.message;

Implicit 隐式$in

Because of schemas, Mongoose knows what types fields should be, so it can provide some neat syntactic sugar. 因为有了模式,Mongoose知道字段应该是什么类型,所以它可以提供一些巧妙的语法糖。For example, if you forget to put $in on a non-array field, Mongoose will add $in for you.例如,如果您忘记在非数组字段中放入$in,Mongoose会为您添加$in

// Normally wouldn't find anything because `name` is a string, but
// Mongoose automatically inserts `$in`
const query = Character.findOne({ name: ['Jean-Luc Picard', 'Will Riker'] });

const doc = await query.exec();
doc.name; // "Jean-Luc Picard"

// `{ name: { $in: ['Jean-Luc Picard', 'Will Riker'] } }`
query.getFilter();