Mongoose中文文档-指南之查询(Queries)

 2018年12月03日    906     声明


Mongoose模型的很多类方法都不能直接返回查询或操作结果,其会返回一个Query对象,我们需要从Query对象中获取操作结果。Query对象是一个链式查询,我们可以在查询过程中引用其它文档,也可以流式的传输查询结果。

  1. Queries
  2. Queries不是Promise
  3. 引用其它文档

1. Queries

Mongoose的模型(Model)为CRUD操作提供了几个静态辅助函数,这些函数中的每个操作都会返回一个mongoose Query对象

以上操作都会返回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会是nullresult会使用查询结果填充。

无论何时将回调传递给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()方法以便于coasync/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首次发布