Mongoose模型的很多类方法都不能直接返回查询或操作结果,其会返回一个Query
对象,我们需要从Query
对象中获取操作结果。Query
对象是一个链式查询,我们可以在查询过程中引用其它文档,也可以流式的传输查询结果。
1. Queries
Mongoose的模型(Model
)为CRUD操作提供了几个静态辅助函数,这些函数中的每个操作都会返回一个mongoose Query
对象。
Model.deleteMany()
Model.deleteOne()
Model.find()
Model.findById()
Model.findByIdAndDelete()
Model.findByIdAndRemove()
Model.findByIdAndUpdate()
Model.findOne()
Model.findOneAndDelete()
Model.findOneAndRemove()
Model.findOneAndUpdate()
Model.replaceOne()
Model.updateMany()
Model.updateOne()
以上操作都会返回Query
对象,该对象默认不会执行查询。可以通过以下两种方式之一执行mongoose查询:
传入回调函数
传入回调函数时,相关操作会立即执行,并会将查询结果传递给回调。
使用回调函数执行查询时,将查询指定为JSON文档。JSON文档的语法与MongoDB shell相同。
var Person = mongoose.model('Person', yourSchema); // find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) { if (err) return handleError(err); // Prints "Space Ghost is a talk show host". console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation); });
如上所示,传入回调函数后查询会立即执行,其结果也会传入到回调函数中。在Mongoose中,所有的回调函数的格式都是:callback(error, result)
。如果执行查询时发生错误,error
参数中会包含错误文档,而result
会是null
;如果查询成功,error
会是null
,result
会使用查询结果填充。
无论何时将回调传递给Mongoose中的查询,回调的格式都是callback(error, results)
。而results
取决于具体的操作:对于findOne()
,会是一个可能为null的单文档;find()
会是文档列表;count()
为文档数;update()
则为受影响的文档数等。可以通过Model API 查看有关传递给回调的更多详细信息。
.exec()方法
查询还有又.then()
函数,因此可以作为promise。
没有传入callback
时,可以像下面这样获取查询结果:
// 查找 last name 为 'Ghost' 的 person var query = Person.findOne({ 'name.last': 'Ghost' }); // 仅查询 `name` 和 `occupation` 字段 query.select('name occupation'); // 稍后执行查询,并通过 callback 获取查询结果 query.exec(function (err, person) { if (err) return handleError(err); // Prints "Space Ghost is a talk show host." console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation); }); // 或者通过 .then() 获取查询结果 query.exec().then((person) => { // Prints "Space Ghost is a talk show host." console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation); }).catch((err) => { handleError(err); })
如上所示,query
变量是一个Query实例。Query
允许你使用链式语法构建查询,而不仅是指定JSON对象。以下2个示例是等效的:
// With a JSON doc Person. find({ occupation: /host/, 'name.last': 'Ghost', age: { $gt: 17, $lt: 66 }, likes: { $in: ['vaporizing', 'talking'] } }). limit(10). sort({ occupation: -1 }). select({ name: 1, occupation: 1 }). exec(callback); // Using query builder Person. find({ occupation: /host/ }). where('name.last').equals('Ghost'). where('age').gt(17).lt(66). where('likes').in(['vaporizing', 'talking']). limit(10). sort('-occupation'). select('name occupation'). exec(callback);
2. Queries不是Promise
Mongoose查询不是Promise。它们有.then()
方法以便于co和async/await使用。 但是,与Promise不同,调用query
的.then()
可以多次执行查询。
在下例中,updateMany()
会执行3次,一次是因为回调函数,而两次是因为.then()
:
const q = MyModel.updateMany({}, { isDeleted: true }, function() { console.log('Update 1'); }); q.then(() => console.log('Update 2')); q.then(() => console.log('Update 3'));
不要在查询中混合使用回调和promise,因为可能会引起重复操作。
3. 引用其它文档
MongoDB中没有连接查询,但有时我们仍然希望引用其他集合中的文档。这时可通过填充( population)来实现。更多关于如何在查询结果中包含其他集合中的文档Query#populate() 。
4. 流
Mongoose支持从MongoDB中流式传输查询结果,需要调用Query#cursor()方法来返回QueryCursor的实例。
下一步
现在我们已经介绍了Queries
,接下来让我们来看看验证-Validation。
变更记录
- [2018-12-03] 基于Mongoose官方文档
v5.3.12
首次发布