模型
模型 是从 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 的 丰富 查询语法。可以使用 model
的 find、findById、findOne 或 where 静态函数检索文档。
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 文档 涵盖了许多其他可用方法,例如 count、mapReduce、aggregate 等等。
下一步
既然我们已经介绍了 Models
,让我们来看看 Documents。