模型
模型 是从 Schema
定义编译而来的奇特构造函数。 模型的一个实例称为 document。 模型负责从底层 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
,包括钩子!
构建文档
模型的一个实例称为 document。 创建它们并将其保存到数据库很容易。
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' }]);
请注意,在模型使用的连接打开之前,不会创建/删除任何水箱。 每个模型都有一个关联的连接。 当你使用 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 的 rich 查询语法。
可以使用 model
的 find、findById、findOne 或 where 静态函数检索文档。
await Tank.find({ size: 'small' }).where('createdDate').gt(oneYearAgo).exec();
有关如何使用 查询 api 的更多详细信息,请参阅有关 queries 的章节。
删除
模型具有静态 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 副本集,否则更改流会执行 not 工作。
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 视图 本质上是只读集合,其中包含使用 aggregations 从其他集合计算得出的数据。
在 Mongoose 中,你应该为每个视图定义一个单独的模型。
你还可以使用 createCollection()
创建视图。
以下示例展示了如何在 User
模型上创建新的 RedactedUser
视图,以隐藏潜在的敏感信息,例如名称和电子邮件。
// 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: 'john.smith@gmail.com', roles: ['user'] },
{ name: 'Bill James', email: 'bill@acme.co', 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
,让我们来看看 文档。