从 6.x 迁移到 7.x
从 Mongoose 6.x 迁移到 Mongoose 7.x 时,你应该注意一些向后破坏的更改。
如果你仍在使用 Mongoose 5.x,请先阅读 Mongoose 5.x 到 6.x 迁移指南 并升级到 Mongoose 6.x。
strictQuery
- 删除了
remove()
- 放弃回调支持
- 删除了
update()
- 鉴别器结构默认使用基本结构选项
- 删除了
castForQueryWrapper()
,更新了castForQuery()
签名 - 复制
Schema.prototype.add()
中的结构选项 - ObjectId bsontype 现在有小写 d
- 删除了对自定义 promise 库的支持
- 删除了 mapReduce
- TypeScript 特定的更改
strictQuery
strictQuery
现在默认为 false。
const mySchema = new Schema({ field: Number });
const MyModel = mongoose.model('Test', mySchema);
// Mongoose will not strip out `notInSchema: 1` because `strictQuery` is false by default
const docs = await MyModel.find({ notInSchema: 1 });
// Empty array in Mongoose 7. In Mongoose 6, this would contain all documents in MyModel
docs;
已删除 remove()
文档和模型上的 remove()
方法已被删除。
请改用 deleteOne()
或 deleteMany()
。
const mySchema = new Schema({ field: Number });
const MyModel = mongoose.model('Test', mySchema);
// Change this:
await MyModel.remove(filter);
// To this:
await MyModel.deleteOne(filter);
// Or this, if you want to delete multiple:
await MyModel.deleteMany(filter);
// For documents, change this:
await doc.remove();
// To this:
await doc.deleteOne();
请记住,deleteOne()
钩子默认被视为查询中间件。
因此对于中间件,请执行以下操作:
// Replace this:
schema.pre('remove', function() {
/* ... */
});
// With this:
schema.pre('deleteOne', { document: true, query: false }, function() {
/* ... */
});
放弃回调支持
以下函数不再接受回调。 他们总是返回 promise。
Aggregate.prototype.exec
Aggregate.prototype.explain
AggregationCursor.prototype.close
Connection.prototype.startSession
Connection.prototype.dropCollection
Connection.prototype.createCollection
Connection.prototype.dropDatabase
Connection.prototype.openUri
Connection.prototype.close
Connection.prototype.destroy
Document.prototype.populate
Document.prototype.validate
Mongoose.prototype.connect
Mongoose.prototype.createConnection
Model.prototype.save
Model.aggregate
Model.bulkWrite
Model.cleanIndexes
Model.countDocuments
Model.create
Model.createCollection
Model.createIndexes
Model.deleteOne
Model.deleteMany
Model.distinct
Model.ensureIndexes
Model.estimatedDocumentCount
Model.exists
Model.find
Model.findById
Model.findByIdAndUpdate
Model.findByIdAndReplace
Model.findOne
Model.findOneAndDelete
Model.findOneAndUpdate
Model.findOneAndRemove
Model.insertMany
Model.listIndexes
Model.replaceOne
Model.syncIndexes
Model.updateMany
Model.updateOne
Query.prototype.find
Query.prototype.findOne
Query.prototype.findOneAndDelete
Query.prototype.findOneAndUpdate
Query.prototype.findOneAndRemove
Query.prototype.findOneAndReplace
Query.prototype.validate
Query.prototype.deleteOne
Query.prototype.deleteMany
Query.prototype.exec
QueryCursor.prototype.close
QueryCursor.prototype.next
如果你将上述函数与回调一起使用,我们建议切换到 async/await,或者在异步函数不适合你时使用 Promise。 如果你需要重构遗留代码库的帮助,请使用 ChatGPT 这个工具从掌握 JS 回调到异步等待。
// Before
conn.startSession(function(err, session) {
// ...
});
// After
const session = await conn.startSession();
// Or:
conn.startSession().then(sesson => { /* ... */ });
// With error handling
try {
await conn.startSession();
} catch (err) { /* ... */ }
// Or:
const [err, session] = await conn.startSession().then(
session => ([null, session]),
err => ([err, null])
);
已删除 update()
Model.update()
、Query.prototype.update()
和 Document.prototype.update()
已被删除。
请改用 updateOne()
。
// Before
await Model.update(filter, update);
await doc.update(update);
// After
await Model.updateOne(filter, update);
await doc.updateOne(update);
鉴别器结构默认使用基本结构选项
当你使用 Model.discriminator()
时,Mongoose 现在将默认使用鉴别器基本结构的选项。
这意味着你不需要显式设置子结构选项来匹配基本结构。
const baseSchema = Schema({}, { typeKey: '$type' });
const Base = db.model('Base', baseSchema);
// In Mongoose 6.x, the `Base.discriminator()` call would throw because
// no `typeKey` option. In Mongoose 7, Mongoose uses the base schema's
// `typeKey` by default.
const childSchema = new Schema({}, {});
const Test = Base.discriminator('Child', childSchema);
Test.schema.options.typeKey; // '$type'
删除了 castForQueryWrapper
,更新了 castForQuery()
签名
Mongoose 现在总是使用 3 个参数调用 SchemaType castForQuery()
方法: $conditional
、value
和 context
。
如果你已经实现了定义其自己的 castForQuery()
方法的自定义结构类型,则需要按如下方式更新该方法。
// Mongoose 6.x format:
MySchemaType.prototype.castForQuery = function($conditional, value) {
if (arguments.length === 2) {
// Handle casting value with `$conditional` - $eq, $in, $not, etc.
} else {
value = $conditional;
// Handle casting `value` with no conditional
}
};
// Mongoose 7.x format
MySchemaType.prototype.castForQuery = function($conditional, value, context) {
if ($conditional != null) {
// Handle casting value with `$conditional` - $eq, $in, $not, etc.
} else {
// Handle casting `value` with no conditional
}
};
复制 Schema.prototype.add()
中的架构选项
Mongoose 现在在将一个结构添加到另一个结构时复制用户定义的结构选项。
例如,下面的 childSchema
将获得 baseSchema
的 id
和 toJSON
选项。
const baseSchema = new Schema({ created: Date }, { id: true, toJSON: { virtuals: true } });
const childSchema = new Schema([baseSchema, { name: String }]);
childSchema.options.toJSON; // { virtuals: true } in Mongoose 7. undefined in Mongoose 6.
这既适用于使用结构数组创建新结构的情况,也适用于如下调用 add()
的情况。
childSchema.add(new Schema({}, { toObject: { virtuals: true } }));
childSchema.options.toObject; // { virtuals: true } in Mongoose 7. undefined in Mongoose 6.
ObjectId bsontype 现在有小写 d
ObjectIds 上的内部 _bsontype
属性等于 Mongoose 7 中的 'ObjectId'
,而不是 Mongoose 6 中的 'ObjectID'
。
const oid = new mongoose.Types.ObjectId();
oid._bsontype; // 'ObjectId' in Mongoose 7, 'ObjectID' in older versions of Mongoose
请更新任何使用 _bsontype
检查对象是否为 ObjectId 的地方。
这也可能会影响使用 Mongoose 的库。
删除了 mapReduce
MongoDB 不再支持 mapReduce
,因此 Mongoose 7 不再有 Model.mapReduce()
功能。
使用聚合框架作为 mapReduce()
的替代品。
// The following no longer works in Mongoose 7.
const o = {
map: function() {
emit(this.author, 1);
},
reduce: function(k, vals) {
return vals.length;
}
};
await MR.mapReduce(o);
删除了对自定义 promise 库的支持
Mongoose 7 不再支持插入自定义 Promise 库。 因此,以下内容不再使 Mongoose 在 Mongoose 7 中返回 Bluebird promise。
const mongoose = require('mongoose');
// No-op on Mongoose 7
mongoose.Promise = require('bluebird');
如果你想使用 Bluebird 实现全局作用域内的所有 promise,你可以执行以下操作:
global.Promise = require('bluebird');
TypeScript 特定的更改
删除了 LeanDocument
并支持 extends Document
Mongoose 7 不再导出 LeanDocument
类型,也不再支持将 extends Document
的文档类型传递到 Model<>
。
// No longer supported
interface ITest extends Document {
name?: string;
}
const Test = model<ITest>('Test', schema);
// Do this instead, no `extends Document`
interface ITest {
name?: string;
}
const Test = model<ITest>('Test', schema);
// If you need to access the hydrated document type, use the following code
type TestDocument = ReturnType<(typeof Test)['hydrate']>;
HydratedDocument
的新参数
Mongoose 的 HydratedDocument
类型将原始文档接口转换为水合 Mongoose 文档的类型,包括虚拟、方法等。在 Mongoose 7 中,HydratedDocument
的通用参数已更改。
在 Mongoose 6 中,通用参数为:
type HydratedDocument<
DocType,
TMethodsAndOverrides = {},
TVirtuals = {}
> = Document<unknown, any, DocType> &
Require_id<DocType> &
TMethodsAndOverrides &
TVirtuals;
在 Mongoose 7 中,新类型如下。
type HydratedDocument<
DocType,
TOverrides = {},
TQueryHelpers = {}
> = Document<unknown, TQueryHelpers, DocType> &
Require_id<DocType> &
TOverrides;
在 Mongoose 7 中,第一个参数是原始文档接口,第二个参数是任何特定于文档的覆盖(通常是虚函数和方法),第三个参数是与文档模型关联的任何查询辅助程序。
主要区别在于,在 Mongoose 6 中,第三个通用参数是文档的虚拟参数。 在 Mongoose 7 中,第三个通用参数是文档的查询助手。
// Mongoose 6 version:
type UserDocument = HydratedDocument<TUser, TUserMethods, TUserVirtuals>;
// Mongoose 7:
type UserDocument = HydratedDocument<TUser, TUserMethods & TUserVirtuals, TUserQueryHelpers>;