MongoDB 2.6 中的兼容性更改

在本页面

以下 2.6 更改可能会影响与旧版本 MongoDB 的兼容性。有关 2.6 更改的完整列表,请参见MongoDB 2.6 发行说明

Index Changes

强制执行索引密钥长度限制

  • Description

    • MongoDB 2.6 对index key实施了更严格的限制。

如果现有文档中的索引键超出限制,则创建索引将出错:

插入错误:

更新将错误:

  • 如果更新的值导致索引条目超过限制,则对索引字段执行的db.collection.update()db.collection.save()操作将出错。

  • 如果现有文档包含其索引条目超过限制的索引字段,则其他导致字段在磁盘上重新定位的字段的更新将出错。

块迁移将失败:

  • 对于具有文档中包含索引字段超过索引限制的索引字段的文档块,迁移将失败。

  • 如果不固定,该块将反复失败迁移,从而有效地停止了该集合的块平衡。或者,如果响应于迁移失败而发生了块拆分,则此响应将导致不必要的大量块和过多的配置数据库。

副本集的次要成员将警告:

  • 次要对象将 continue 使用索引字段(其对应的索引条目超过初始同步限制)复制文档,但将在日志中显示警告。

  • 辅助数据库允许对包含索引字段的集合进行索引构建和重建操作,该索引字段的相应索引条目超过了限制,但日志中有警告。

  • 对于辅助目录为 2.6 版且主目录为 2.4 版的* mixed version *副本集,辅助目录将复制在 2.4 主目录上插入或更新的文档,但是如果文档包含其索引对应的索引字段,则会在日志中显示错误消息条目超过限制。

  • Solution

    • 运行db.upgradeCheckAllDBs()查找违反此限制的当前密钥,并进行适当的更正。最好在升级之前运行测试;也就是说,将 2.6 mongo shell 连接到您的 MongoDB 2.4 数据库并运行该方法。

如果您已有数据集,并且想要禁用默认的索引键长度验证,以便可以在解决这些索引问题之前进行升级,请使用failIndexKeyTooLong参数。

索引规范验证字段名称

  • Description

    • 在 MongoDB 2.6 中,当索引键引用一个空字段时,例如创建和重新索引操作将失败。 "a..b" : 1或字段名以美元符号($)开头。
  • db.collection.ensureIndex()不会使用无效或空的键名创建新索引。

  • 如果存在具有无效或空键名的索引,则db.collection.reIndex()compactrepairDatabase将出错。

  • 如果存在具有无效或空键名的索引,则块迁移将失败。

MongoDB 的早期版本允许索引。

  • Solution

    • 运行db.upgradeCheckAllDBs()查找违反此限制的当前密钥,并进行适当的更正。最好在升级之前运行测试;也就是说,将 2.6 mongo shell 连接到您的 MongoDB 2.4 数据库并运行该方法。

确保索引和现有索引

db.mycollection.ensureIndex( { x: 1 } )
db.mycollection.ensureIndex( { x: 1 }, { unique: 1 } )
  • 如果指定的索引名称已经存在,但键的规格不同;例如在以下示例中,第二个db.collection.ensureIndex()将出错。
db.mycollection.ensureIndex( { a: 1 }, { name: "myIdx" } )
db.mycollection.ensureIndex( { z: 1 }, { name: "myIdx" } )

以前的版本没有创建索引,但是没有错误。

写入方法确认

[1]在以前的版本中,当交互式使用mongo shell 时,mongo shell 在 write 方法之后会自动调用getLastError命令以提供对写入的确认。但是,除非脚本在 write 方法之后包含对getLastError命令的“显式”调用,否则脚本在以前的版本中将观察到“即发即弃”的行为。
  • Solution

    • 使用这些mongo shell 方法进行具有“即发即忘”行为的批量写入操作的脚本应使用Bulk()方法。

在分片环境中,插入或修改文档组时,使用任何驱动程序或mongo shell 的应用程序应使用Bulk()方法以获得最佳性能。

例如,代替:

for (var i = 1; i <= 1000000; i++) {
    db.test.insert( { x : i } );
}

在 MongoDB 2.6 中,替换为Bulk()操作:

var bulk = db.test.initializeUnorderedBulkOp();

for (var i = 1; i <= 1000000; i++) {
    bulk.insert( { x : i} );
}

bulk.execute( { w: 1 } );

批量方法返回包含操作结果的BulkWriteResult对象。

db.collection.aggregate() Change

  • Description

    • mongo Shell 中的db.collection.aggregate()方法默认为将游标返回到结果集。此更改使聚合管道可以返回任何大小的结果集,并且需要迭代游标才能访问结果集。例如:
var myCursor = db.orders.aggregate( [
    {
      $group: {
         _id: "$cust_id",
         total: { $sum: "$price" }
      }
    }
] );

myCursor.forEach( function(x) { printjson (x); } );

早期版本返回的单个文档的字段results包含结果集数组,但受BSON 文件大小限制。访问 MongoDB 早期版本中的结果集需要访问results字段并迭代数组。例如:

var returnedDoc = db.orders.aggregate( [
    {
      $group: {
         _id: "$cust_id",
         total: { $sum: "$price" }
      }
    }
] );

var myArray = returnedDoc.result; // access the result field

myArray.forEach( function(x) { printjson (x); } );

写关注验证

  • Description

    • 现在,将包含j: true到使用--nojournal选项运行的mongodmongos实例指定写关注点错误。以前的版本会忽略j: true
  • Solution

    • 当针对使用--nojournalmongodmongos实例发布j: true规范时,请从写入关注中删除,或者使用日志记录运行mongodmongos

Security Changes

新的授权模型

  • Description

    • MongoDB 2.6 authorization model更改了 MongoDB 存储和 Management 用户特权信息的方式:
  • 升级之前,MongoDB 2.6 在 Management 数据库中至少需要一个用户。

  • 使用旧模型的 MongoDB 版本无法创建/修改用户或创建用户定义的角色。

  • Solution

    • 确保 Management 数据库中至少存在一个用户。如果 Management 数据库中没有用户,请添加用户。然后升级到 MongoDB 2.6. 最后,升级用户权限模型。参见将 MongoDB 升级到 2.6

Important

在升级授权模型之前,您应该首先将 MongoDB 二进制文件升级到 2.6. 对于分片群集,请确保所有群集组件均为 2.6. 如果在任何数据库中都有用户,则在升级 MongoDB 二进制文件之前,请确保至少有一个userAdminAnyDatabase角色的用户在admin数据库中。

SSL 证书主机名验证

  • Description

    • 现在,SSL 证书验证将检查“公用名(CN)”和“使用者备用名(SAN)”字段,以确保CNSAN条目之一与服务器的主机名匹配。结果,如果您当前使用 SSL,并且当前 SSL 证书的CN条目或所有SAN条目都与主机名都不匹配,则升级到 2.6 版将导致 SSL 连接失败。
  • Solution

  • mongodmongos绕过群集中其他服务器上的 SSL 证书验证。

  • mongo shell,支持 SSL 的 MongoDB 工具和 C 驱动程序绕过服务器证书的验证。

使用allowInvalidCertificates设置时,MongoDB 将使用无效证书记录为警告。

Warning

allowInvalidCertificates设置会绕过其他证书验证,例如检查过期和有效签名。

2dsphere 索引版本 2

  • Description

    • MongoDB 2.6 引入了2dsphere index的版本 2.如果文档缺少2dsphere索引字段(或者该字段是null或空数组),则 MongoDB 不会将文档的条目添加到2dsphere索引中。对于插入,MongoDB 插入文档,但不添加到2dsphere索引。

先前版本不会插入2dsphere索引字段是null或空数组的文档。对于缺少2dsphere索引字段的文档,以前的版本将插入文档并为其构建索引。

  • Solution

    • 若要还原为旧行为,请使用{ "2dsphereIndexVersion" : 1 }创建2dsphere索引以创建版本 1 索引。但是,版本 1 索引不能使用新的 GeoJSON 几何。

See also

Log Messages

时间戳格式更改

  • Description

    • 现在,每条消息都以时间格式变更中给出的时间戳格式开始。以前的版本使用ctime格式。
  • Solution

    • MongoDB 添加了一个新选项--timeStampFormat,该选项支持ctimeiso8601-utciso8601-local的时间戳格式(新的默认值)。

软件包配置更改

RPM/DEB 软件包的默认 bindIp

  • Description

    • 在 RPM(Red Hat,CentOS,Fedora Linux 和衍生产品)和 DEB(Debian,Ubuntu 和衍生产品)中的正式 MongoDB 软件包中,默认的bindIp值将 MongoDB 组件附加到 localhost 接口* only *。这些软件包在默认配置文件(即/etc/mongod.conf)中设置了此默认设置。
  • Solution

    • 如果您使用这些软件包之一,并且没有修改默认的/etc/mongod.conf文件,则需要在升级之前或升级过程中设置bindIp

其他任何官方 MongoDB 软件包中均没有默认的bindIp设置。

SNMP Changes

  • Description

      • MongoDB 的 IANA 企业标识符从 37601 更改为 34601.
  • MongoDB 将 MIB 字段名称globalopcounts更改为globalOpcounts

  • Solution

      • SNMP 监控的用户必须将其 SNMP 配置(即 MIB)从 37601 修改为 34601.
  • 将对globalopcounts的引用更新为globalOpcounts

删除方法签名更改

  • Description

    • db.collection.remove()需要查询文档作为参数。在以前的版本中,没有查询文档的方法调用会删除集合中的所有文档。
  • Solution

    • 对于没有查询文档的现有db.collection.remove()调用,请修改这些调用以包括一个空文档db.collection.remove({})

更新运算符语法验证

{ $set: { } }
{ $set: { a: 5 }, $set: { b: 5 } }

更新强制字段名称限制

  • Description

  • 更新不再支持保存包含点(.)或以美元符号($)开头的字段名称的字段名称。

  • Solution

  • 对于名称字段包含点(.)的现有文档,请替换整个文档或unset替换该字段。要查找名称包含点的字段,请运行db.upgradeCheckAllDBs()

  • 对于现有字段名称以美元符号($),unsetrename开头的现有文档。要查找名称以美元符号开头的字段,请运行db.upgradeCheckAllDBs()

有关写入操作协议的更改,请参见新的写操作协议;有关插入和更新操作的更改,请参见插入和更新改进。还请考虑字段名称限制的文档。

查询和排序更改

强制执行字段名称限制

  • Description

    • 查询不能在名称以美元符号($)开头的字段上指定条件。
  • Solution

稀疏索引和不完整结果

  • Description

    • 如果sparse index导致查询和排序操作的结果集不完整,除非hint()明确指定索引,否则 MongoDB 将不会使用该索引。

例如,除非明确提示,否则查询{ x: { $exists: false } }将不再在x字段上使用稀疏索引。

  • Solution

    • 要覆盖使用稀疏索引并返回不完整结果的行为,请使用hint()显式指定索引。

有关详细说明新行为的示例,请参见集合上的稀疏索引无法返回完整结果

sort()规范值

  • Description

    • sort()方法“仅” **接受以下排序键值:
  • 1指定字段的升序,

  • -1指定字段的降序,或者

  • $meta表达式以指定按文本搜索分数排序。

任何其他值都将导致错误。

以前的版本也接受truefalse进行升序。

  • Solution

    • 将使用truefalse的排序键值更新为1

skip()和_id 查询

  • Description

    • _id字段上的相等匹配服从skip()

_id字段上执行相等匹配时,以前的版本会忽略skip()

describe()保留查询计划缓存

在以前的版本中,explain()具有清除该查询形状的查询计划缓存的副作用。

See also

PlanCache()参考。

Geospatial Changes

$maxDistance Changes

在以前的版本中,$maxDistance可以在$near文档之内或之外。

Deprecated $uniqueDocs

  • Description

    • MongoDB 2.6 弃用$uniqueDocs,并且当文档多次匹配查询时,地理空间查询不再返回重复的结果。

加强地理空间查询的验证

  • Description

    • MongoDB 2.6 加强了对地理空间查询的验证,例如验证选项或 GeoJSON 规范,如果地理空间查询无效,则会出错。先前版本允许/忽略无效选项。

查询运算符更改

$ not 查询行为更改

  • Description

      • 现在在索引字段上具有$not表达式的查询将匹配:
  • 缺少索引字段的文档。以前的版本不会使用索引返回这些文档。

    • 索引字段值与指定值的类型不同的文档。以前的版本不会使用索引返回这些文档。

例如,如果集合orders包含以下文档:

{ _id: 1, status: "A", cust_id: "123", price: 40 }
{ _id: 2, status: "A", cust_id: "xyz", price: "N/A" }
{ _id: 3, status: "D", cust_id: "xyz" }

如果集合在price字段上具有索引:

db.orders.ensureIndex( { price: 1 } )

以下查询使用索引来搜索price不大于或等于50的文档:

db.orders.find( { price: { $not: { $gte: 50 } } } )

在 2.6 中,查询返回以下文档:

{ "_id" : 3, "status" : "D", "cust_id" : "xyz" }
{ "_id" : 1, "status" : "A", "cust_id" : "123", "price" : 40 }
{ "_id" : 2, "status" : "A", "cust_id" : "xyz", "price" : "N/A" }

在以前的版本中,索引计划仅在字段类型与查询谓词类型匹配的情况下返回匹配的文档:

{ "_id" : 1, "status" : "A", "cust_id" : "123", "price" : 40 }

如果使用集合扫描,则以前的版本将返回与 2.6 中相同的结果。

  • MongoDB 2.6 允许链接$not表达式。

空比较查询

  • Description

      • null$lt$gt比较不再匹配缺少该字段的文档。
  • 数组元素(例如"a.b": null)上的null个相等条件不再匹配缺少嵌套字段a.b(例如a: [ 2, 3 ])的文档。

  • null相等查询(即field: null)现在将值undefined的字段匹配。

$ all 操作员行为更改

  • Description

      • 现在,$all运算符等效于指定值的$and运算。当传递单个嵌套数组(例如[ [ "A" ] ])的数组时,这种行为上的变化可以比以前的版本进行更多匹配。当传递嵌套数组的数组时,$all现在可以匹配文档,其中该字段包含嵌套数组作为元素(例如field: [ [ "A" ], ... ]),或者字段等于嵌套数组(例如field: [ "A", "B" ])。较早的版本只能匹配字段包含嵌套数组的文档。
  • 如果 array 字段包含嵌套数组(例如field: [ "a", ["b"] ]),并且嵌套字段上的$all是嵌套数组的元素(例如"field.1": { $all: [ "b" ] }),则$all运算符不返回任何匹配项。早期版本将返回匹配项。

$ mod 运算符强制使用严格的语法

在以前的版本中,如果传递的数组包含一个元素,则$mod运算符将0用作第二个元素,如果传递的数组包含两个以上的元素,则$mod会忽略除前两个元素之外的所有元素。以前的版本在传递空数组时会返回错误。

  • Solution

    • 确保传递给$mod的数组恰好包含两个元素:
  • 如果数组包含单个元素,请添加0作为第二个元素。

  • 如果数组包含两个以上的元素,请删除多余的元素。

$必须位于顶层

  • Description

    • $where表达式现在只能位于顶层,不能嵌套在另一个表达式中,例如$elemMatch
  • Solution

    • 更新嵌套$where的现有查询。

$存在且值得注意

如果 MongoDB 服务器已禁用集合扫描,即notablescan,则$exists没有“索引解决方案”的查询将出错。

MinKey 和 MaxKey 查询

  • Description

    • MinKeyMaxKey的相等匹配不再匹配缺少该字段的文档。

具有$ elemMatch 的嵌套数组查询

  • Description

    • $elemMatch查询运算符不再递归遍历嵌套数组。

例如,如果集合test包含以下文档:

{ "_id": 1, "a" : [ [ 1, 2, 5 ] ] }

在 2.6 中,以下$elemMatch查询与文档不匹配*:

db.test.find( { a: { $elemMatch: { $gt: 1, $lt: 5 } } } )
  • Solution

    • 更新依赖于旧行为的现有查询。

文本搜索兼容性

MongoDB 不支持在同时包含 2.4 版和 2.6 版分片的混合分片群集部署中使用$text查询运算符。有关升级说明,请参见将 MongoDB 升级到 2.6

副本集/共享群集验证

分片名称检查刷新元数据

  • Description

    • 对于分片群集,如果未明确设置分片名称,则 MongoDB 2.6 禁止分片刷新元数据。

对于同时包含 2.4 版和 2.6 版分片的混合分片群集部署,如果分片名称对于 2.6 版分片是未知的,则从 2.4 版分片**迁移到 2.6 版分片时,此更改可能导致错误。 。 MongoDB 不支持在混合分片群集部署中进行迁移。

副本集投票配置验证

  • Description

    • 现在,MongoDB 不赞成给任何replica set成员多于一次投票。在配置过程中,local.system.replset.members[n].votes对于投票成员而言应仅为 1,对于非投票成员而言应为 0. MongoDB 将非 1 或 0 的值视为 1,并生成警告消息。
  • Solution

    • local.system.replset.members[n].votes的值更新为 1 或 0 以外的值,以 1 或 0 为宜。

时间格式更改

现在,在许多输出中格式化时间数据时,MongoDB 现在使用iso8601-local。此格式遵循模板YYYY-MM-DDTHH:mm:ss.mmm<+/-Offset>。例如2014-03-04T20:13:38.944-0500

此更改会影响在“严格模式”下使用Extended JSON的所有 Client 端,例如mongoexport

Other Resources