本页介绍MongoDB 9.0 中引入的更改,这些更改可能会影响与旧版本MongoDB的兼容性。
弃用
已弃用 | 说明 |
|---|---|
| 从MongoDB 9.0 开始,使用 |
| 您无法覆盖针对MongoDB 9.0 中加密的子字符串查询的内部限制。 |
聚合(Aggregation)
中的空字段名称 $group
从MongoDB 9.0 开始,如果累加器表达式的字段名称为空,则 $group 阶段会返回错误。有关详细信息,请参阅空字段名称 $群组限制。
allowPartialResults 在聚合 $queryStats 键中
Starting in MongoDB 9.0, the $queryStats key for aggregate commands includes the allowPartialResults option when the option is explicitly set. Query stats can then distinguish between requests where allowPartialResults is omitted, explicitly true, or explicitly false.
该添加更改了设立allowPartialResults 的 aggregate 查询的 key 和 keyHash 序列化。 queryShapeHash 保持不变。在 keyHash 上匹配的下游使用者可能会观察到这些查询的不同值。
查询语言
对遍历数组的虚线路径进行空值比较
从MongoDB 9.0 开始,未解析为非空值的虚线路径的计算结果为 null。当路径中的字段包含空大量、标量值大量或包含嵌套大量的大量时,将应用新行为。在早期版本中,这些路径不会计算为 null,这会产生与 $exists 不一致的结果。
考虑一个包含以下文档的collection:
{ _id: 1, a: [ 1 ] } { _id: 2, a: [ ] }
在任一文文档中,路径 a.b 均未解析为非空值。从MongoDB 9.0 开始,{ "a.b": null }查询会匹配两个文档。在早期版本中,查询与两个文档都不匹配。 { "a.b": { $ne: null } }查询返回相反的结果:在MongoDB 9.0 中,该查询匹配两个文档,而在早期版本中,它匹配两个文档。
MongoDB不会遍历嵌套数组,因此本身就是大量的元素永远不会解析路径的其余部分。考虑一个包含以下文档的集合:
{ _id: 3, a: [ [ { b: 3 } ] ] } { _id: 4, a: [ [ { b: 2 } ], { b: 3 } ] }
_id: 3 中的每个 b 值和 _id: 4 中 2 的 b 值都位于嵌套大量内,因此路径 a.b 不会到达它们。从MongoDB 9.0 开始,{ "a.b": null }查询会同时匹配两个文档,而 { "a.b": { $ne: null } }查询不会匹配任何文档。在早期版本中,{ "a.b": null }查询与两个文档都不匹配。嵌套大量会导致 _id: 4 匹配 { "a.b": null },即使其第二个元素将 a.b 解析为非空值 3。
新行为会影响使用$eq、$ne、$in、$nin、$gte 和 $lte 操作符的与 null 的比较。 $lookup 阶段中的等值匹配遵循相同的语义。
升级影响
在升级到MongoDB 9.0 之前,查看将虚线路径与 null 进行比较的查询和 $lookup 阶段。如果路径中的字段包含空大量、标量值大量或包含嵌套大量的大量,则这些查询会在升级后返回不同的结果集。使用 { $ne: null } 查找存在虚线路径且不是 null 的文档的查询返回的文档较少,而使用 { $eq: null } 的查询返回的文档较多。
一般性变更
当带索引的字段变为多键时,查询会失败
从MongoDB 9.0 开始,如果索引字段成为多键字段,而引用该字段的查询正在运行,则查询可能会失败并显示QueryKilledError。当您插入或更新文档时,索引字段将变为多键,因此该字段包含大量值。
如果查询因此错误而失败,请在插入或更新操作完成后重新运行查询。
变更流在选举后强制执行读取偏好
Starting in MongoDB 9.0, a change stream opened with a readPreference of primary or secondary returns the resumable error InterruptedDueToReplStateChange (error code 11602) from getMore if a replica set election changes the node's role so that it no longer satisfies the read preference. In earlier versions, the cursor kept returning results from the same node.
兼容的驱动程序和 mongos 会从上一个恢复令牌自动恢复。手动 getMore 循环和 mongosh 必须使用 resumeAfter 来恢复。有关详细信息,请参阅恢复变更流。
地理空间索引键提取错误代码
从MongoDB 9.0 开始,2dsphere索引键提取失败会返回指定的错误代码 510 (GeoKeyExtractionFailed) 和 511 (GeoKeyExtractionFailedTimeseries)。这些代码取代了之前用于常规 2dsphere 索引的断言代码 16755 和 16756,以及用于时间序列集合的 183934 和 183493。如果您的应用程序与以前的代码匹配,请对其更新以匹配 510 和 511。
更强的跨数据库集合锁 renameCollection
从MongoDB 9.0 开始,当您在副本集上的不同数据库之间重命名集合时,renameCollection 命令会对源集合和目标集合持有独占锁。该锁会持续整个操作,并阻止 DDL 操作和写入两个集合。大多数读取操作都使用无锁读取,并且不会被阻止。
早期版本在 renameCollection 完成重命名之前释放了源集合的锁。在此窗口期间对源集合的并发写入可能会丢失。
此更改仅影响副本集。分片集群已在重命名期间锁这两个集合。
服务器端JavaScript日期操作使用 UTC
从MongoDB 9.0 开始,服务器端JavaScript在基于 WebAssembly (WASM) 的引擎上运行,该引擎以 UTC 格式评估本地 Date 操作,而与mongod托管位于哪个时区域无关。在早期版本中,这些操作遵循托管时区域。此更改会影响在 $function、$accumulator、$where 和 mapReduce 下运行的JavaScript 。
存储的BSON日期值保持不变,Date.prototype.getTime()、Date.prototype.toISOString() 和 getUTC*() 方法等 UTC 操作也是如此。这种差异会影响本地时间操作:
Date.prototype.toString()Date.prototype.toTimeString()Date.prototype.getHours()和其他本地 getter本地
Date构造函数和 setter将日期隐式转换为字符串的操作,包括不使用比较器调用的
Array.prototype.sort()
考虑在与 TZ=America/New_York 一起运行的 mongod 上执行以下操作:
db.events.insertOne( { name: "before-opening", occurredAt: ISODate("2024-01-15T13:30:00Z") } ) db.events.find( { $expr: { $function: { body: function(date) { return date.getHours() < 9; }, args: [ "$occurredAt" ], lang: "js" } } } )
在早期版本中,13:30 UTC 是纽约的 08:30,因此 getHours() 返回 8,并且查询与文档匹配。从MongoDB 9.0 开始,getHours() 返回 13,且查询不匹配。该操作在两个版本中都会成功,因为存储的日期仍然有效,因此差异不会报告为错误。运行混合二进制版本的部署可能会为相同的JavaScript返回不同的结果。
升级影响
Before you upgrade to MongoDB 9.0, review the JavaScript in your $function, $accumulator, $where, and mapReduce code for local Date usage, and do not rely on the mongod host time zone.
要评估已命名时区域中的日期,请使用带有显式 timezone 参数的聚合日期操作符,而不是JavaScript。以下查询在所有版本中返回相同的结果:
db.events.find( { $expr: { $lt: [ { $hour: { date: "$occurredAt", timezone: "America/New_York" } }, 9 ] } } )
对于需要确定性比较或序列化的JavaScript ,请使用 getTime()、toISOString() 或 getUTC*() 方法,而不是本地 Date 方法或隐式字符串转换。当排序后的值可以包含日期时,向 Array.prototype.sort() 传递一个显式比较器。
要学习;了解更多信息,请参阅 服务器端JavaScript。
服务器端JavaScript不可用于 ppc64le
从MongoDB 9.0 开始,服务器端JavaScript在 ppc64le 架构上不可用。 ppc64le 的 mongod 和mongos 二进制文件不包含JavaScript引擎。因此,$function、$accumulator、$where 和 mapReduce 操作在该架构上失败。早期版本在 ppc64le 上运行这些操作。
您无法使用配置文件设置或命令行选项在 ppc64le 上启用服务器端JavaScript 。
升级影响
在将 ppc64le部署升级到MongoDB 9.0 之前,请确定使用$function、$accumulator、$where 或 mapReduce 的应用程序。重写这些操作以使用不需要服务器端JavaScript 的聚合管道阶段和操作符。还可以在使用不同架构的部署上运行这些操作。
要学习;了解更多信息,请参阅 服务器端JavaScript。
安全性
Queryable Encryption前缀、后缀和子字符串公开预览版到 GA 迁移
MongoDB 9.0 标记对已启用可Queryable Encryption的集合中的加密字符串字段进行前缀、后缀和子字符串查询的 GA。 GA功能与MongoDB 8.2 中发布的公共预览版不兼容,既然该功能是 GA 版本,则不应使用该公共预览版。
要将前缀、后缀或子字符串查询与Queryable Encryption结合使用, MongoDB必须为 9.0 或更高版本,并具有 9.0 兼容驱动程序。如果您仍在使用公共预览版,MongoDB必须保留在带有 8.2 或 8.3 兼容驱动程序的 8.2 或 8.3 版本。
MongoDB 9.0 驱动程序可以解密使用MongoDB 8.2 或 8.3 驱动程序创建的数据。有关升级选项,请参阅以下部分。
重新开始(首选)
如果可能,请创建新集合,而不是迁移使用公共预览功能创建的集合:
将MongoDB服务器和驱动程序升级到 9.0。
配置新的加密集合,其名称与之前的集合不同。
插入新数据,或如有本地副本,则插入现有数据的未加密版本。
删除以前的集合。
迁移现有数据
如果不能使用新数据或没有现有数据的未加密版本:
将MongoDB服务器和驱动程序升级到 9。0
使用 9.0 兼容驾驶员,查询加密集合以将其解密。
将输出保存在本地。
配置新的加密集合并接收数据。
警告
mongoexport和mongodump操作不会解密集合。您必须从驾驶员查询集合才能输出解密的数据。MongoDB 9.0 兼容驱动程序无法查询针对MongoDB 8.2 公共预览版查询类型的加密加密的加密字段。要解密数据,请查询未加密的字段或查询整个集合。
向后不兼容的功能
以下部分提供了从部署中删除向后不兼容功能的信息。如果您要从MongoDB 9.0 降级到早期版本,查看以下部分,确保您的部署在降级后成功运行。
视图中的表达式
在MongoDB 9.0 中,$convert 可以将对象转换为 binData。有关详细信息,请参阅将对象转换为 binData。
如果您创建的视图使用此转换,则在您降级到早期版本后,对该视图的查询会返回错误。
在从 9.0 降级之前,更新或删除使用此转换的任何视图。