查询转换
¥Query Casting
Model.find()
、Query#find()
、Model.findOne()
等的第一个参数称为 filter
。在较旧的内容中,此参数有时称为 query
或 conditions
。例如:
¥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
. For 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 } }`
当你使用 Query#exec()
或 Query#then()
执行查询时,Mongoose 会转换过滤器以匹配你的结构。
¥When you execute the query using Query#exec()
or Query#then()
, Mongoose casts the filter to match your schema.
// 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
如果 Mongoose 无法将过滤器转换为你的结构,你的查询将抛出 CastError
。
¥If Mongoose fails to cast the filter to your schema, your query will throw a 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"
err.message;
strictQuery
选项
¥The strictQuery
Option
默认情况下,Mongoose 不会强制转换不在你的架构中的过滤器属性。
¥By default, Mongoose does not cast filter properties that aren't in your schema.
const query = Character.findOne({ notInSchema: { $lt: 'not a number' } });
// No error because `notInSchema` is not defined in the schema
await query.exec();
你可以使用 结构的 strictQuery
选项.conf 配置此行为。此选项类似于 strict
选项。将 strictQuery
设置为 true
会从过滤器中删除非结构属性:
¥You can configure this behavior using the strictQuery
option for schemas. This option is analogous to the strict
option. Setting strictQuery
to true
removes non-schema properties from the filter:
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`
如果你的 filter
具有不在结构中的属性,要使 Mongoose 抛出错误,请将 strictQuery
设置为 'throw'
:
¥To make Mongoose throw an error if your filter
has a property that isn't in the schema, set strictQuery
to '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;
隐式 $in
¥Implicit $in
由于结构的存在,Mongoose 知道字段应该是什么类型,因此它可以提供一些简洁的语法糖。例如,如果你忘记将 $in
放在非数组字段上,Mongoose 将为你添加 $in
。
¥Because of schemas, Mongoose knows what types fields should be, so it can provide some neat syntactic sugar. For example, if you forget to put $in
on a non-array field, Mongoose will add $in
for you.
// 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();