☰
Mongoose 5.x 升级 6.x 迁移指南:破坏性变更全解析与源码级应对方案
2026/10/7 23:34:17 网站建设 项目流程

Mongoose 5.x 升级 6.x 迁移指南:破坏性变更全解析与源码级应对方案

【免费下载链接】mongooseMongoDB object modeling designed to work in an asynchronous environment.项目地址: https://gitcode.com/GitHub_Trending/mo/mongoose

本文以 Mongoose 官方迁移文档为主体,系统梳理从 Mongoose 5.x 升级到 6.x 过程中所有破坏性变更(breaking changes),包括 MongoDB Driver 4.0 升级、连接与查询 API 的 Promise 化、strictQuery/sanitizeFilter等新行为,以及 TypeScript 类型变化。文中每个变更点均结合当前仓库源码(lib/mongoose.js、lib/query.js、lib/schema.js等)给出实现依据与可复制的迁移代码,帮助你在升级前完成影响面评估、升级中精准改码、升级后规避隐蔽行为差异。

前置提示:Mongoose 5 已于 2024 年 3 月 1 日停止支持,官方版本支持策略详见 docs/version-support.md。如果你仍在使用 Mongoose 4.x,请先阅读 docs/migrating_to_5.md 升级到 5.x,再按本文升级到 6.x。

一、升级前评估:版本要求与整体路线

1.1 运行环境要求

  • Node.js:Mongoose 6 要求Node.js >= 12.0.0。
  • MongoDB Server:仍支持 MongoDB Server 3.0.0 及以上版本。

升级前请先确认生产环境的 Node 运行时满足要求,避免升级依赖后出现语法或 API 兼容问题。

1.2 底层驱动升级:MongoDB Driver 4.0

Mongoose 6 底层改用 MongoDB Node.js Driver v4.x,这是本次升级中影响面最大的底层变更。值得关注的变化包括:

  • TypeScript 类型定义冲突:Driver 4.x 由 TypeScript 编写并自带类型定义,可能与@types/mongodb冲突。若出现编译器报错,请确保升级到最新的@types/mongodb(新版本为空 stub)。
  • 连接池选项更名:poolSize被拆分为minPoolSize与maxPoolSize。Mongoose 5.x 的poolSize等价于 6.x 的maxPoolSize,且maxPoolSize默认值提高到了100。在 lib/mongoose.js 的connect()/createConnection()文档注释中可以看到maxPoolSize默认 100、minPoolSize默认 0 的约定,MongoDB 同一时刻每个 socket 只允许一个操作,若存在慢查询阻塞快查询的场景可适当调大maxPoolSize。
  • updateOne()/updateMany()返回值变化:
const res = await TestModel.updateMany({}, { someProperty: 'someValue' }); res.matchedCount; // 匹配过滤条件的文档数,替代 `res.n` res.modifiedCount; // 实际被修改的文档数,替代 `res.nModified` res.upsertedCount; // upsert 的文档数,替代 `res.upserted`
  • deleteOne()/deleteMany()返回值不再有n属性:
const res = await TestModel.deleteMany({}); // Mongoose 6:`{ acknowledged: true, deletedCount: 2 }` // Mongoose 5:`{ n: 2, ok: 1, deletedCount: 2 }` res; res.deletedCount; // 被删除的文档数,替代 `res.n`

凡是依赖res.n、res.nModified、res.upserted的存量代码,升级后必须改为访问matchedCount、modifiedCount、upsertedCount、deletedCount。

二、连接层变更:清理废弃选项与 Promise 化

2.1 移除四个 Deprecation Warning 选项

useNewUrlParser、useUnifiedTopology、useFindAndModify、useCreateIndex四个选项在 Mongoose 6 中不再受支持。Mongoose 6 的行为等价于useNewUrlParser、useUnifiedTopology、useCreateIndex恒为true,useFindAndModify恒为false,请直接删除代码中的这些选项:

// 不再需要: mongoose.set('useFindAndModify', false); await mongoose.connect('mongodb://127.0.0.1:27017/test', { useNewUrlParser: true, // <-- 不再需要 useUnifiedTopology: true // <-- 不再需要 });

2.2 Connection 不再 thenable:改用asPromise()

Mongoose 6 中 connection 不再是 thenable,await mongoose.createConnection(uri)不再等待连接建立。从 lib/mongoose.js 的源码可以看到,createConnection()同步创建 Connection 实例并立即返回,连接通过conn.openUri(uri, { ...options, _fireAndForget: true })异步进行。若需要等待连接完成,必须显式调用asPromise():

// 以下写法在 Mongoose 6 中不再生效 await mongoose.createConnection(uri); // 请改为: await mongoose.createConnection(uri).asPromise();

2.3mongoose.connect()始终返回 Promise

mongoose.connect()现在总是返回 Promise(resolve 为 Mongoose 实例),而不再是 Mongoose 实例本身。源码中Mongoose.prototype.connect是async function,且传入回调函数会直接抛出MongooseError('Mongoose.prototype.connect() no longer accepts a callback')(见 lib/mongoose.js)。连接失败时await会抛出MongooseServerSelectionError。同样地,mongoose.disconnect()也不再接受回调。

三、查询行为变更

3.1 禁止重复执行同一查询对象

Mongoose 6 不再允许对同一个 query 对象执行两次,否则抛出Query was already executed错误。该错误由 lib/query.js 中的throw new MongooseError('Query was already executed: ' + str)产生。重复执行通常意味着回调与 Promise 混用;如需再次执行,请使用Query#clone():

// 会报 'Query was already executed' 错误,因为这次 `find()` 实际执行了两次 await Model.find({}, function(err, result) {}); const q = Model.find(); await q; await q.clone(); // 用 `clone()` 克隆查询后可再次执行

3.2Model.exists()返回 lean 文档而非布尔值

Mongoose 6 中Model.exists()不再返回布尔值,而是返回{ _id: ObjectId(...) }或null:

// Mongoose 5.x 中 `existingUser` 是布尔值 // 现在 `existingUser` 为 `{ _id: ObjectId(...) }` 或 `null` const existingUser = await User.exists({ name: 'John' }); if (existingUser) { console.log(existingUser._id); }

3.3strictQuery默认跟随strict

Mongoose 6.0.10 起恢复了strictQuery选项,并将其默认值设为与strict一致(默认true)。这意味着默认情况下,Mongoose 会过滤掉查询过滤条件中不在 schema 里的属性。注意:Mongoose 7 起该默认值改回false。如果你希望保留 Mongoose 5 以及 7+ 的默认行为,可以全局关闭:

mongoose.set('strictQuery', false);

strictQuery支持true、false、'throw'三种取值。在测试套件中设为'throw'很有用——任何查询引用 schema 中不存在的字段都会抛异常,有助于暴露测试或代码中的 bug(当前仓库中该选项的默认值定义在 lib/mongoose.js 的set()文档注释里,为false)。

strictQuery的实际效果示例:

const userSchema = new Schema({ name: String }); const User = mongoose.model('User', userSchema); // 默认等价于 `User.find()`,因为 Mongoose 会过滤掉 `notInSchema` await User.find({ notInSchema: 1 }); // 设置 `strictQuery: false` 允许按 schema 之外的属性过滤 await User.find({ notInSchema: 1 }, null, { strictQuery: false }); // 等价写法: await User.find({ notInSchema: 1 }).setOptions({ strictQuery: false });

3.4 查询过滤器安全加固:sanitizeFilter与trusted()

Mongoose 6 引入sanitizeFilter选项(可作用于全局或单个查询),用于防御query selector 注入攻击。开启后,Mongoose 会把过滤条件中任何包含$开头的键的对象用$eq包裹。

从 lib/helpers/query/sanitizeFilter.js 的实现可以看到其具体策略:

  • 递归处理$and/$or/$nor内部的对象;
  • 对含$键的对象(且不是单独的$eq)包装为{ $eq: 原对象 };
  • 对$jsonSchema、$where、$expr、$text直接抛出MongooseError,明确禁止与sanitizeFilter同用;
  • 打上trustedSymbol标记的对象会被跳过(见 lib/helpers/query/trusted.js,通过Symbol('mongoose#trustedSymbol')实现)。
// Mongoose 会把该过滤器转换为 `{ username: 'val', pwd: { $eq: { $ne: null } } }`, // 从而阻止 query selector 注入。 await Test.find({ username: 'val', pwd: { $ne: null } }).setOptions({ sanitizeFilter: true });

如需显式放行某个 query selector,使用mongoose.trusted():

// `mongoose.trusted()` 允许 query selector 原样通过 await Test.find({ username: 'val', pwd: mongoose.trusted({ $ne: null }) }).setOptions({ sanitizeFilter: true });

mongoose.sanitizeFilter()与mongoose.trusted()均暴露在 Mongoose 实例上(见 lib/mongoose.js 与 lib/mongoose.js)。

3.5 移除omitUndefined:undefined键默认被剔除

Mongoose 5.x 中,在更新操作里把键设为undefined等价于设为null;5.x 还提供了omitUndefined选项来剥离undefined键。Mongoose 6 中:

  • omitUndefined选项已被移除;
  • Mongoose 始终剥离undefined键,不再置为null。
// Mongoose 6 中,等价于 `findOneAndUpdate({}, {}, { new: true })`, // 因为 Mongoose 会移除 `name: undefined` const res = await Test.findOneAndUpdate({}, { $set: { name: undefined } }, { new: true });

唯一的工作区是显式把属性设为null:

const res = await Test.findOneAndUpdate({}, { $set: { name: null } }, { new: true });

3.6Model.exists()之外:create()空数组返回空数组

await Model.create([])在 v6.0 中传入空数组时返回空数组,v5.0 中返回undefined。如果代码中有对返回值是否为undefined的判断,需要改为:只要传入的是数组,await Model.create(...)就始终返回数组。

3.7 副本集场景的disconnected事件

连接副本集时,Mongoose 6 在失去与主节点的连接时就会触发disconnected事件;而 Mongoose 5 只有在失去与副本集所有成员的连接时才触发。但需要注意,Mongoose 6不会在连接处于 disconnected 状态时缓冲命令,因此即使 Mongoose connection 处于 disconnected 状态,仍可正常执行readPreference = 'secondary'之类的查询。

四、Schema 与数据建模变更

4.1 Discriminator Schema 默认克隆

Mongoose 6 默认克隆 discriminator schema。如果使用递归嵌入式 discriminator,需要显式传入{ clone: false }:

// 在 Mongoose 6 中,以下两者等价: User.discriminator('author', authorSchema); User.discriminator('author', authorSchema.clone()); // 如果 `clone()` 引发问题,可传 `clone: false` 退出该行为 User.discriminator('author', authorSchema, { clone: false });

4.2isValidObjectId()简化与新的isObjectIdOrHexString()

Mongoose 5 中mongoose.isValidObjectId()对数字等值返回false,与 MongoDB 驱动的ObjectId.isValid()行为不一致。Mongoose 6 中isValidObjectId()只是mongoose.Types.ObjectId.isValid()的包装(见 lib/mongoose.js),而任何 JavaScript 数字技术上都能转换为 ObjectId,因此返回值会出乎意料。

Mongoose 6.2.5 新增mongoose.isObjectIdOrHexString(),它更贴合isValidObjectId()的常见使用场景:判断给定值是否为ObjectId实例或 24 位十六进制字符串。其实现见 lib/mongoose.js:isBsonType(v, 'ObjectId') || (typeof v === 'string' && /^[0-9A-Fa-f]{24}$/.test(v))。

// `isValidObjectId()` 会对一些意外的值返回 `true`, // 因为这些值_技术上_是 ObjectId 的表现形式 mongoose.isValidObjectId(new mongoose.Types.ObjectId()); // true mongoose.isValidObjectId('0123456789ab'); // true mongoose.isValidObjectId(6); // true mongoose.isValidObjectId(new User({ name: 'test' })); // true // `isObjectIdOrHexString()` 只对 ObjectId 实例和 24 位十六进制字符串返回 `true` mongoose.isObjectIdOrHexString(new mongoose.Types.ObjectId()); // true mongoose.isObjectIdOrHexString('62261a65d66c6be0a63c051f'); // true mongoose.isObjectIdOrHexString('0123456789ab'); // false mongoose.isObjectIdOrHexString(6); // false

4.3 Schema 定义的文档键顺序

Mongoose 6 按schema 中定义键的顺序保存文档,而不是按用户传入对象的键顺序。Object.keys(new User({ name: String, email: String }).toObject())返回['name', 'email']还是['email', 'name'],取决于 schema 中name与email的定义顺序:

const schema = new Schema({ profile: { name: { first: String, last: String } } }); const Test = db.model('Test', schema); const doc = new Test({ profile: { name: { last: 'Musashi', first: 'Miyamoto' } } }); // 注意 'first' 排在 'last' 之前,尽管 `new Test()` 的参数颠倒了键序。 // Mongoose 使用 schema 的键顺序,而不是传入对象的键顺序。 assert.deepEqual(Object.keys(doc.toObject().profile.name), ['first', 'last']);

4.4default函数接收文档参数

Mongoose 6 会把文档作为第一个参数传给default函数,这对箭头函数形式的默认值非常有用:

const schema = new Schema({ name: String, age: Number, canVote: { type: Boolean, // default 函数现在接收 `doc` 参数,便于使用箭头函数 default: doc => doc.age >= 18 } });

注意:如果传入的默认函数并不需要文档参数(比如default: mongoose.Types.ObjectId),请改为default: () => myFunction(),避免意外传入参数改变行为。

4.5 数组是 Proxy:不再需要markModified()

Mongoose 6 的数组是 ES6 Proxy,直接按索引赋值后无需再调用markModified():

const post = await BlogPost.findOne(); post.tags[0] = 'javascript'; await post.save(); // 直接生效,无需 `markModified()`!

4.6typePojoToMixed移除:对象字面量成为子文档

type: { name: String }声明的 schema 路径在 Mongoose 6 中变成单嵌套子文档,而不是 Mongoose 5 中的 Mixed,因此不再需要typePojoToMixed选项:

// Mongoose 6 中,下面使 `foo` 成为带 `name` 属性的子文档。 // Mongoose 5 中,除非设置 `typePojoToMixed: false`,否则 `foo` 是 Mixed 类型。 const schema = new Schema({ foo: { type: { name: String } } });

4.7 保留字路径警告

使用save、isNew等 Mongoose 保留字作为 schema 路径名,现在触发警告而非错误。仓库 lib/schema.js 中维护了保留字列表(save、isNew、validate、remove、collection、init等),当路径名命中保留字且未设置suppressReservedKeysWarning时会打印警告(见 lib/schema.js)。

可通过 schema 选项抑制警告:

new Schema({ save: String }, { suppressReservedKeysWarning: true });

但请留意:这可能导致依赖这些保留字的插件失效。

4.8 子文档路径重命名

单嵌套子文档被重命名为 "subdocument paths"(子文档路径):

  • SchemaSingleNestedOptions→SchemaSubdocumentOptions
  • mongoose.Schema.Types.Embedded→mongoose.Schema.Types.Subdocument

对应地,仓库中 schema 类型目录里也保留了subdocument.js(如 lib/schema/subdocument.js)与类型定义 types/subdocument.d.ts。

4.9 移除嵌套路径合并

doc.set({ child: { age: 21 } })现在无论child是嵌套路径还是子文档,行为一致:覆盖child的值。Mongoose 5 中,若child是嵌套路径,该操作会进行合并。

4.10 ObjectId 新增valueOf()

Mongoose 6 给 ObjectId 增加了valueOf()函数,因此可以用==把 ObjectId 与字符串直接比较:

const a = ObjectId('6143b55ac9a762738b15d4f0'); a == '6143b55ac9a762738b15d4f0'; // true

4.11createdAt默认不可变

设置timestamps: true后,Mongoose 6 会把createdAt属性设为immutable,防止更新操作误改创建时间。仓库中时间戳实现位于 lib/helpers/timestamps/setupTimestamps.js。若业务确实需要修改createdAt,可通过timestamps.createdAt.immutable选项调整(mongoose.set('timestamps.createdAt.immutable', false),对应说明见 lib/mongoose.js)。

4.11 移除isAsync验证器与safe选项

  • isAsync不再是validate的选项,请改用async function编写异步验证器。
  • safe不再是 schema、query 或save()的选项,请改用writeConcern。

4.12 SchemaTypeset函数参数变化

Mongoose 6 中 setter 函数的第二个参数从schemaType(Mongoose 5)变为priorValue(前一个值),第三个参数才是schemaType:

const userSchema = new Schema({ name: { type: String, trimStart: true, set: trimStartSetter } }); // v5.x 参数为 (value, schemaType),v6.x 参数为 (value, priorValue, schemaType) function trimStartSetter(val, priorValue, schemaType) { if (schemaType.options.trimStart && typeof val === 'string') { return val.trimStart(); } return val; } const User = mongoose.model('User', userSchema); const user = new User({ name: 'Robert Martin' }); console.log(user.name); // 'robert martin'

4.13toObject()/toJSON()使用嵌套 schema 的minimize

toObject()与toJSON()默认使用各层嵌套 schema 自身的minimize选项,而不是顶层 schema 的。该变更随 5.10.5 发布,但从 5.9.x 直接升 6.x 的用户容易踩坑:

const child = new Schema({ thing: Schema.Types.Mixed }); const parent = new Schema({ child }, { minimize: false }); const Parent = model('Parent', parent); const p = new Parent({ child: { thing: {} } }); // v5.10.4:因 `toObject()` 使用 `parent` schema 的 `minimize` 选项,会包含 `child.thing` // `>= 5.10.5`:`child` schema 的 `minimize: true`,`child.thing` 被省略 console.log(p.toObject());

两种工作区:

// 方案一:显式传 `minimize` 给 `toObject()` 或 `toJSON()` console.log(p.toObject({ minimize: false }));
// 方案二(仅 Mongoose 6):内联定义 `child` schema,继承父级 `minimize` 选项 const parent = new Schema({ // 隐式创建新 schema,并继承顶层 schema 的 `minimize` 选项 child: { type: { thing: Schema.Types.Mixed } } }, { minimize: false });

五、Populate 相关变更

5.1strictPopulate():populate 未定义路径报错

Mongoose 6 在populate()一个 schema 中未定义的路径时会抛出错误。该行为仅适用于能推断本地 schema 的场景(如Query#populate()),不适用于对 POJO 调用Model.populate()。

5.2 子文档ref函数上下文

populate 子文档时,若ref或refPath是函数,this/参数指向正在被 populate 的子文档,而不是顶层文档:

const schema = new Schema({ works: [{ modelId: String, data: { type: mongoose.ObjectId, ref: function(doc) { // Mongoose 6 中 `doc` 是数组元素,因此可以访问 `modelId`。 // Mongoose 5 中 `doc` 是顶层文档。 return doc.modelId; } } }] });

5.3 自定义验证器使用反 populate 路径

Mongoose 6 始终以反 populate 后的路径(即 id 而非文档本身)调用验证器。Mongoose 5 在路径被 populate 时会把填充后的文档传给验证器。

5.4 移除execPopulate()

Document#populate()现在直接返回 Promise,且不再可链式调用:

  • 将await doc.populate('path1').populate('path2').execPopulate();替换为await doc.populate(['path1', 'path2']);
  • 将await doc.populate('path1', 'select1').populate('path2', 'select2').execPopulate();替换为:
await doc.populate([{path: 'path1', select: 'select1'}, {path: 'path2', select: 'select2'}]);

5.5Query.prototype.populate()不再有默认 model

Mongoose 5 中,对 Mixed 类型等没有ref的路径调用populate()会回退使用查询所属的 model:

const testSchema = new mongoose.Schema({ data: String, parents: Array // Array of mixed }); const Test = mongoose.model('Test', testSchema); // 下面的 `populate()`... await Test.findOne().populate('parents'); // 在 Mongoose 5 中是如下 populate 的简写 await Test.findOne().populate({ path: 'parents', model: Test });

Mongoose 6 中,populate 一个没有ref、refPath或model的路径是no-op(无操作):

// 下面的 `populate()` 什么也不做。 await Test.findOne().populate('parents');

六、聚合与索引行为变更

6.1 创建聚合游标

Aggregate#cursor()现在直接返回AggregationCursor实例,与Query#cursor()保持一致。不再需要Model.aggregate(pipeline).cursor().exec(),直接Model.aggregate(pipeline).cursor()即可。

6.2autoCreate默认true

autoCreate默认开启(除非readPreference为secondary或secondaryPreferred),Mongoose 会在创建索引前尝试为每个 model 创建底层集合。从源码看,全局默认选项autoIndex: true、autoCreate: true定义在 lib/mongoose.js。当readPreference为 secondary 或 secondaryPreferred 时,autoCreate与autoIndex都会默认变为false,因为连接从节点时createCollection()与createIndex()都会失败。

6.3 移除context: 'query'选项

query 的context选项已被移除,Mongoose 现在始终使用context = 'query'。

七、其他重要行为变化

7.1MongoError更名为MongoServerError

MongoDB Node.js Driver v4.x 中'MongoError'已更名为'MongoServerError'。请修改所有依赖硬编码字符串'MongoError'的代码。

7.2 Driver 新 URL 解析器与部分 npm 包的兼容性问题

Mongoose 6 依赖的 MongoDB Driver 使用 whatwg-url。

7.3 移除reconnectTries与reconnectInterval

这两个选项已被移除,且不再必要。MongoDB Node.js Driver 会在serverSelectionTimeoutMS(默认 30000ms,即 30 秒,见 lib/mongoose.js)内持续重试任何操作,即使 MongoDB 长时间宕机也不会耗尽重试次数或主动断线重连。

7.4 LodashisEmpty()对 ObjectId 返回true

Lodash 的isEmpty()对原始类型及原始类型包装对象返回true。ObjectId()是被 Mongoose 视为原始类型的对象包装器,但从 Mongoose 6 起,由于 Lodash 的实现细节,_.isEmpty()会对 ObjectId 返回true。Mongoose 中的 ObjectId 永远不会为空,因此使用isEmpty()时应额外检查instanceof ObjectId:

if (!(val instanceof Types.ObjectId) && _.isEmpty(val)) { // 在此处理空对象 }

7.5 移除mongoose.modelSchemas

mongoose.modelSchemas属性已被移除(它曾被用来删除某个 model schema),请改用mongoose.deleteModel():

// 之前 delete mongoose.modelSchemas.User; // Mongoose 6.x delete mongoose.deleteModel('User');

deleteModel()的实现见 lib/mongoose.js,同时支持字符串与 RegExp(例如mongoose.deleteModel(/.+/)删除全部 model),在测试清理场景非常实用。

八、TypeScript 类型变化

8.1Schema泛型参数从 4 个变为 3 个

Schema类现在接收 3 个泛型参数(原来是 4 个)。第 3 个泛型参数SchemaDefinitionType现在与第 1 个泛型参数DocType相同。请把new Schema<UserDocument, UserModel, User>(schemaDefinition)替换为new Schema<UserDocument, UserModel>(schemaDefinition)。

8.2Types.ObjectId是类:必须使用new

Types.ObjectId现在是一个类,创建新 ObjectId 时不能省略new。JavaScript 中目前仍可省略new,但TypeScript 中必须写new:

const id = new mongoose.Types.ObjectId(); // TypeScript 必须带 new

8.3 移除的遗留类型

以下遗留类型已被移除:

  • ModelUpdateOptions
  • DocumentQuery
  • HookSyncCallback
  • HookAsyncCallback
  • HookErrorCallback
  • HookNextFunction
  • HookDoneFunction
  • SchemaTypeOpts
  • ConnectionOptions

8.4 virtual getter/setter 中this类型推断

Mongoose 6 会在 virtual getter 和 setter 中推断文档类型。Mongoose 5.x 中,下面代码里的this是any:

schema.virtual('myVirtual').get(function() { this; // Mongoose 5.x 中为 any });

Mongoose 6 中this会被推断为文档类型:

const schema = new Schema({ name: String }); schema.virtual('myVirtual').get(function() { this.name; // string });

九、迁移检查清单

升级到 Mongoose 6 后,建议逐项核对以下要点:

  1. 环境:Node.js ≥ 12;MongoDB Server ≥ 3.0。
  2. 连接代码:删除useNewUrlParser/useUnifiedTopology/useFindAndModify/useCreateIndex;createConnection()后如需等待连接用.asPromise();connect()不再接受回调。
  3. 返回值:update*与delete*改用matchedCount/modifiedCount/upsertedCount/deletedCount;Model.exists()按 lean 文档处理;Model.create([])返回空数组。
  4. 查询:不要重复执行同一 query;需要复用用clone();按需设置strictQuery(测试环境可用'throw');有不可信输入时开启sanitizeFilter。
  5. Schema:default函数会收到 doc 参数;数组索引赋值免markModified();createdAt默认 immutable;对象字面量类型路径变为子文档。
  6. Populate:移除execPopulate(),用数组形式的populate();无ref的 populate 是 no-op;未定义路径的 populate 会抛错。
  7. TypeScript:Schema泛型减为 3 个;new mongoose.Types.ObjectId()必须带new;删除已废弃的类型引用。
  8. 行为细节:文档键顺序按 schema 定义排列;toObject()/toJSON()的minimize逐层生效;ObjectId 可用==与字符串比较;LodashisEmpty()对 ObjectId 返回true;用deleteModel()替代modelSchemas删除。

如需进一步查阅本仓库中的相关实现,可关注:lib/mongoose.js(连接与全局选项)、lib/query.js(查询执行与Query was already executed错误)、lib/schema.js(保留字与 schema 行为)、lib/helpers/query/sanitizeFilter.js 与 lib/helpers/query/trusted.js(过滤器净化)、lib/helpers/timestamps/setupTimestamps.js(时间戳与 immutablecreatedAt)。完整的变更历史可参考仓库根目录的 CHANGELOG.md,若准备继续升级到更高版本,可阅读 docs/migrating_to_7.md 与 docs/migrating_to_8.md、docs/migrating_to_9.md 等后续迁移文档。

【免费下载链接】mongooseMongoDB object modeling designed to work in an asynchronous environment.项目地址: https://gitcode.com/GitHub_Trending/mo/mongoose

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询