Mongoose 是一个 Node.js 中非常流行的 MongoDB ODM(Object Data Modeling,对象数据映射)库,它可以轻松地对 MongoDB 进行操作。然而,在使用 Mongoose 时,有一些需要注意的陷阱,本文将为你详细介绍这些陷阱以及如何避免它们。
1. 避免混淆同名集合
在 Mongoose 中,每个 model 与一个 MongoDB 集合相对应,并且默认情况下,集合的名称是 model 名称的复数形式。例如,一个名为 User
的 model 对应于一个名为 users
的集合。如果你采用了下面的方式来创建 model:
const User = mongoose.model('User', userSchema, 'users');
其中第三个参数指定集合的名称为 users
,它与 model 名称一致,这就容易造成混淆。为避免这种情况,建议统一使用集合名称的复数形式(即不指定第三个参数),这样就不会发生混淆。
2. 关闭自动重连
Mongoose 默认情况下会进行自动重连,即在 MongoDB 数据库故障时自动尝试重新连接。但这可能会导致一些问题,例如,如果你自己手动关闭了数据库,Mongoose 会不停地尝试重连,这会浪费大量资源。
为了避免这种情况,可以在连接数据库时添加一个选项:
mongoose.connect(uri, { autoReconnect: false });
这样就可以避免自动重连了。当然,如果你需要自动重连,则可以将这个选项改为 true
。
3. 使用 schema 的 type
属性
在 Mongoose 中,schema 是定义 model 的核心部分。在定义 schema 时,我们通常会使用下面的方式:
const userSchema = new mongoose.Schema({ name: String, email: String, age: Number });
这样就定义了一个包含三个属性的 schema。然而,上面的例子中,我们没有为每个属性指定 type
属性。这是因为,当我们没有指定 type
时,Mongoose 会根据属性值的类型自动推断属性的类型。
例如,上面的 name
和 email
属性都是字符串类型,因此 Mongoose 会把它们的 type
自动设为 String
。然而,如果你使用了类似下面的方式:
const userSchema = new mongoose.Schema({ name: { type: String }, email: { type: String }, age: { type: Number } });
虽然这样指定 type
属性不会造成什么问题,但这样做肯定有些繁琐。因此,在定义 schema 时不必指定 type
属性,这可以令代码更加简洁。
4. 避免混淆 model 和 document
在 Mongoose 中,model 和 document 是两个不同的概念。model
是 Mongoose 的核心部分,它代表一个 MongoDB 集合,并且负责定义 schema、创建 document、进行查询等操作。document
则代表集合中的一个实例,它由一个 model 创建而来,可以被直接操作、读取和修改。
因此,在使用 Mongoose 时,需要时刻注意两者的区别。例如,应该将 model 名称用 Model
结尾,而将 document 名称用 Document
结尾,这样可以更易于区分。同时,也不要忘记每个 document 的 _id
属性,它是 MongoDB 中每个 document 的唯一标识。
5. 使用 Promise
Mongoose 的很多操作都是异步的,例如连接数据库、删除数据、查询数据等等。通常情况下,我们可以使用回调函数来处理这些异步操作,例如:
User.findOne({ name: 'john' }, function(err, user) { if (err) return handleError(err); console.log(user); });
然而,使用回调函数可能会导致回调地狱,代码难以维护。因此,在 Mongoose 中,使用 Promise 更加方便。例如,你可以把上面的代码重写成:
User.findOne({ name: 'john' }) .then(user => { console.log(user); }) .catch(err => { handleError(err); });
当然,使用 Promise 也需要注意一些细节,例如,需要确保同时使用 resolve()
和 reject()
。
6. 不要使用 save
方法
在 Mongoose 中,你可以使用 save
方法来保存一个 document。例如:
const user = new User({ name: 'john' }); user.save(function(err) { if (err) return handleError(err); console.log('User saved!'); });
然而,使用 save
方法可能会导致一些问题,例如:
- 它会自动将所有属性进行保存,即使这些属性没有变化也会覆盖存在的数据。
- 它是一个异步操作,性能不高。
- 如果需要更新一个 document,必须先查询这个 document,然后将新的值传递给这个 document 并调用它的
save
方法,这会增加代码难度和复杂度。
因此,在大多数情况下,推荐使用 updateOne
或 updateMany
方法来更新一个 document,例如:
User.updateOne({ _id: id }, { age: 30 }) .then(result => { console.log(result); }) .catch(err => { handleError(err); });
总结
在使用 Mongoose 时,需要注意避免上述的陷阱和问题。为了确保代码的可读性和维护性,建议在定义 schema 时不必指定每个属性的 type
,而应该统一使用集合名称的复数形式,同时使用 Promise 对异步操作进行处理。另外,不要使用 save
方法,而应该使用 updateOne
或 updateMany
方法来更新 document。通过避免这些问题,你可以更加高效地使用 Mongoose,从而更好地完成前端开发工作。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6492728548841e98940420af