模型

模型 是从 Schema 定义编译而成的特殊构造函数。模型的实例称为 文档。模型负责从底层的 MongoDB 数据库创建和读取文档。

编译您的第一个模型

当您在模式上调用 mongoose.model() 时,Mongoose 会为您编译一个模型。

const schema = new mongoose.Schema({ name: String, size: String });
const Tank = mongoose.model('Tank', schema);

第一个参数是您的模型所属集合的单数名称。**Mongoose 会自动查找模型名称的复数形式,并将其小写。** 因此,对于上面的示例,Tank 模型对应于数据库中的 tanks 集合。

注意:.model() 函数会复制 schema。请确保在调用 .model() 之前已将您想要添加到 schema 的所有内容都添加进去,包括钩子!

构建文档

模型的实例称为 文档。创建它们并保存到数据库非常容易。

const Tank = mongoose.model('Tank', yourSchema);

const small = new Tank({ size: 'small' });
await small.save();

// or

await Tank.create({ size: 'small' });

// or, for inserting large batches of documents
await Tank.insertMany([{ size: 'small' }]);

请注意,在模型使用的连接打开之前,不会创建/删除任何 tanks。每个模型都与一个关联的连接相关联。当您使用 mongoose.model() 时,您的模型将使用默认的 mongoose 连接。

await mongoose.connect('mongodb://127.0.0.1/gettingstarted');

如果您创建自定义连接,请使用该连接的 model() 函数。

const connection = mongoose.createConnection('mongodb://127.0.0.1:27017/test');
const Tank = connection.model('Tank', yourSchema);

查询

使用 Mongoose 查找文档非常容易,它支持 MongoDB 的 丰富 查询语法。可以使用 modelfindfindByIdfindOnewhere 静态函数检索文档。

await Tank.find({ size: 'small' }).where('createdDate').gt(oneYearAgo).exec();

有关如何使用 Query API 的更多详细信息,请参阅关于 查询 的章节。

删除

模型具有静态的 deleteOne()deleteMany() 函数,用于删除与给定 filter 匹配的所有文档。

await Tank.deleteOne({ size: 'large' });

更新

每个 model 都有自己的 update 方法,用于修改数据库中的文档,而不会将其返回到您的应用程序。有关更多详细信息,请参阅 API 文档。

// Updated at most one doc, `res.nModified` contains the number
// of docs that MongoDB updated
await Tank.updateOne({ size: 'large' }, { name: 'T-90' });

如果您想更新数据库中的单个文档并将其返回到您的应用程序,请使用 findOneAndUpdate

变更流

变更流 提供了一种方法,您可以通过它监听所有通过 MongoDB 数据库的插入和更新。请注意,变更流只有在您连接到 MongoDB 副本集 时才有效。

async function run() {
  // Create a new mongoose model
  const personSchema = new mongoose.Schema({
    name: String
  });
  const Person = mongoose.model('Person', personSchema);

  // Create a change stream. The 'change' event gets emitted when there's a
  // change in the database
  Person.watch().
    on('change', data => console.log(new Date(), data));

  // Insert a doc, will trigger the change stream handler above
  console.log(new Date(), 'Inserting doc');
  await Person.create({ name: 'Axl Rose' });
}

上面 异步函数 的输出将类似于您在下面看到的。

2018-05-11T15:05:35.467Z 'Inserting doc' 2018-05-11T15:05:35.487Z 'Inserted doc' 2018-05-11T15:05:35.491Z { _id: { _data: ... }, operationType: 'insert', fullDocument: { _id: 5af5b13fe526027666c6bf83, name: 'Axl Rose', __v: 0 }, ns: { db: 'test', coll: 'Person' }, documentKey: { _id: 5af5b13fe526027666c6bf83 } }

您可以在 这篇博文中了解有关 mongoose 中变更流的更多信息.

视图

MongoDB 视图 本质上是只读集合,它们包含使用 聚合 从其他集合计算出来的数据。在 Mongoose 中,您应该为每个视图定义一个单独的模型。您也可以使用 createCollection() 创建视图。

以下示例显示了如何创建新的 RedactedUser 视图,该视图基于 User 模型,并隐藏了可能敏感的信息,例如姓名和电子邮件。

// Make sure to disable `autoCreate` and `autoIndex` for Views,
// because you want to create the collection manually.
const userSchema = new Schema({
  name: String,
  email: String,
  roles: [String]
}, { autoCreate: false, autoIndex: false });
const User = mongoose.model('User', userSchema);

const RedactedUser = mongoose.model('RedactedUser', userSchema);

// First, create the User model's underlying collection...
await User.createCollection();
// Then create the `RedactedUser` model's underlying collection
// as a View.
await RedactedUser.createCollection({
  viewOn: 'users', // Set `viewOn` to the collection name, **not** model name.
  pipeline: [
    {
      $set: {
        name: { $concat: [{ $substr: ['$name', 0, 3] }, '...'] },
        email: { $concat: [{ $substr: ['$email', 0, 3] }, '...'] }
      }
    }
  ]
});

await User.create([
  { name: 'John Smith', email: '[email protected]', roles: ['user'] },
  { name: 'Bill James', email: '[email protected]', roles: ['user', 'admin'] }
]);

// [{ _id: ..., name: 'Bil...', email: 'bil...', roles: ['user', 'admin'] }]
console.log(await RedactedUser.find({ roles: 'admin' }));

请注意,Mongoose 目前 强制执行视图为只读。如果您尝试从视图中 save() 文档,您将从 MongoDB 服务器收到错误。

还有更多

API 文档 涵盖了许多其他可用方法,例如 countmapReduceaggregate 等等。

下一步

既然我们已经介绍了 Models,让我们来看看 Documents