本文介紹MongoDB 3.6版本的相容性變化。
如需查看MongoDB官網相容性更新說明文檔,請前往MongoDB官網下載。
本地主機綁定相容性變更
從MongoDB 3.6開始,MongoDB的mongod和mongos二進位檔案,預設綁定到本地主機。若設定檔中設定了net.ipv6參數或通過命令列選項--ipv6啟用了IPv6支援,程式會額外綁定到本地主機的IPv6地址。
自MongoDB 2.6版本起,僅官方提供的RPM包(適用於Red Hat、CentOS、Fedora Linux及其衍生系統)和DEB包(適用於Debian、Ubuntu及其衍生系統)的二進位程式預設綁定到localhost。
當僅綁定到localhost時,MongoDB 3.6的這些程式僅接受來自同一台機器上用戶端的串連(包括mongo shell、複本集的其他成員或分區叢集的節點)。遠程用戶端將無法串連到僅綁定localhost的執行個體。
若需覆蓋預設行為並綁定到其他IP地址,可通過設定檔中的net.bindIp參數或命令列選項--bind_ip指定主機名稱或IP地址清單。
在綁定到非本地主機(例如公開可訪問的IP地址)之前,請確保已對叢集進行安全強化以防止未授權訪問。至少應啟用身分識別驗證並強化網路基礎設施。
例如,以下mongod執行個體綁定了本地主機與主機名稱My-Example-Associated-Hostname,後者與IP地址198.51.100.1相關聯:
mongod --bind_ip localhost,My-Example-Associated-Hostname為了串連到該執行個體,遠程用戶端必須指定主機名稱或其關聯的IP地址198.51.100.1:
mongo --host My-Example-Associated-Hostname
mongo --host 198.51.100.1分區叢集
自MongoDB 3.6版本起,分區(Shard)必須為複本集(Replica Set)。若要將分區叢集升級到3.6版本,所有分區伺服器必須以複本集形式運行。
HTTP介面與REST API
自MongoDB 3.6版本起,HTTP介面及針對MongoDB的REST API被正式移除。
配置 | mongod/mongos選項 |
|
|
|
|
|
|
|
|
工具更新
MongoDB 3.6刪除了mongooplog工具。
數組操作相容性變更
$type: "array"行為變更
自MongoDB 3.6版本起,type: "array"及$type: 4運算式將匹配包含任意元素類型的數組欄位。
在3.6之前的版本中,$type: "array" 僅匹配包含嵌套數組的數組欄位。
例如,集合 c 包含以下文檔:
{ "_id": 1, "a": [ 1, 2, 3 ] },
{ "_id": 2, "a": [ 1, 2, [ 3, 4 ] ] }以下操作通過欄位 a 的類型進行查詢:
db.c.find( { "a": { $type : "array" } } )從3.6版本開始,此查詢將返回集合中的兩個文檔,因為 $type 查詢現在能檢測到欄位 a 本身是數組:
{ "_id": 1, "a": [ 1, 2, 3 ] },
{ "_id": 2, "a": [ 1, 2, [ 3, 4 ] ] }在MongoDB 3.4及更早版本中,此查詢僅返回欄位 a 包含BSON數群組類型元素的文檔:
{ "_id": 2, "a": [ 1, 2, [ 3, 4 ] ] }如果您當前的MongoDB執行個體版本為3.4.x並且正在使用partialFilterExpression包含$type: "array" 或 $type: 4的部分索引,則升級到3.6後必須重建這些索引,以避免因 $type: 'array' 語義變更引發衝突。
數組排序行為變更
自MongoDB 3.6版本起,當對包含數組的欄位進行排序時,MongoDB在升序排序中會以數組的最小元素值作為排序依據,降序排序則以數組的最大元素值為依據。排序時不再考慮查詢謂詞對數組元素的篩選。此行為變更適用於find命令和彙總管道操作。
當前依賴數組欄位排序的應用程式可能會因該變更導致排序結果與之前版本不同。
結合MongoDB 4.4版本對數組欄位排序行為的進一步調整,若對使用多鍵索引的數組欄位進行排序,查詢計劃將包含阻塞式排序階段(blocking sort stage),除非滿足以下條件:
所有排序欄位的索引邊界為
[MinKey, MaxKey]。多鍵索引欄位的邊界路徑首碼與排序模式無重疊。
find方法排序行為
在MongoDB中,排序依據元素是指排序過程中用於比較含數組欄位的文檔時所選取的數組元素。升序排序時,數組內最小元素值作為排序依據的文檔會優先排列;降序排序時則依據最大元素值。
不同版本的排序行為區別如下:
MongoDB 3.4及更早版本:對數組欄位排序時,會結合查詢條件式篩選數組元素來確定排序依據。
MongoDB 3.6及之後版本:排序依據元素的選擇不再考慮查詢條件,僅基於數組本身的元素值。
升級至MongoDB 3.6後,若應用程式依賴數組欄位排序且包含查詢條件,需驗證排序邏輯是否因行為變更受到影響,必要時調整代碼以保證相容性。
樣本如下:
假設集合 coll 包含以下文檔:
{ _id: 0, a: [-3, -2, 2, 3] }
{ _id: 1, a: [ 5, -4 ] }執行針對數組欄位 a 的查詢與排序操作:
db.coll.find({a: {$gte: 0}}).sort({a: 1});在MongoDB 3.6中,排序依據元素為數組中最小值(忽略查詢條件):
_id: 0的數組a最小值是 -3。_id: 1的數組a最小值是 -4。
返回結果為(按升序排列):
{ "_id" : 1, "a" : [ 5, -4 ] } { "_id" : 0, "a" : [ -3, -2, 2, 3 ] }在MongoDB 3.4及之前版本中,排序依據元素為匹配查詢條件
{$gte: 0}的最小元素:_id: 0的匹配元素為[2, 3],取最小值 2。_id: 1的匹配元素為[5],取最小值 5。
返回結果為(按升序排列):
{ _id: 0, a: [-3, -2, 2, 3] } { _id: 1, a: [ 5, -4 ] }
彙總方法排序行為變更
自MongoDB 3.6版本起,使用db.collection.aggregate()對數組欄位排序時,僅以數組中的單個元素作為排序依據。
樣本如下:
// Documents.
{ "_id" : 1, "timestamps" : [ ISODate("2017-07-15T15:31:01Z"), ISODate("2017-07-21T18:31:01Z") ] }
{ "_id" : 0, "timestamps" : [ ISODate("2017-07-21T15:31:01Z"), ISODate("2017-07-21T13:31:01Z") ] }
// Query.
db.c.aggregate([{$sort: {timestamps: -1}}])在MongoDB 3.6版本中:
降序排序時,取數組中的最晚時間作為排序依據:
_id: 0的數組取 7月21日15:31。_id: 1的數組取 7月21日18:31。
結果按時間降序排列,文檔
_id: 1(18:31)排在_id: 0(15:31)之前。
在3.6之前版本中,排序依據為整個數組逐元素比較。例如:
// Documents.
{_id: 0, a: [3, 1, 5]}
{_id: 1, a: [3, 4, 0]}
// Query.
db.coll.aggregate([{$sort: {a: 1}}])在3.6之前的版本中,排序依據為完整數組 [3,1,5] 與 [3,4,0]:
首元素相同(均為3),比較次元素:
1 < 4結果文檔
_id: 0排在_id: 1之前。
彙總管道中對多數組欄位的複合排序限制
自MongoDB 3.6版本起,在彙總管道中進行排序時,若排序欄位涉及並行數組(即排序欄位為BSON對象中的同級數組元素),MongoDB無法完成排序。以下情況不視為並行數組:
排序鍵為嵌套數組(例如欄位路徑包含層級關係)。
排序鍵共用同一數組作為路徑首碼。
此限制在find命令中一直存在,但3.6版本後find與aggregate的排序語義已統一。
樣本一:嵌套數組可排序
集合包含文檔如下:
{a: [ {b: [1, 2]}, {b: [3, 4]} ]}執行以下彙總操作(排序鍵為嵌套數組欄位):
db.coll.aggregate([{$sort: {"a.b": 1}}])操作成功,因
a.b為嵌套數組欄位,不構成並行數組。樣本二:共用相同數組首碼可排序
集合包含文檔如下:
{a: [{b: 1, c: 1}, {b: 2, c: 2}]}執行以下彙總操作(排序鍵共用同一數組首碼):
db.coll.aggregate([{$sort: {"a.b": 1, "a.c": 1}}])操作成功,因
a.b與a.c共用首碼a,不視為並行數組。樣本三:同級數組導致排序失敗
集合包含文檔如下:
{ _id: 1, a: [ 1, 2 ], b: [ 1, 2 ]} { _id: 2, a: [ -3, 5 ], b: 0 } { _id: 3, a: [ -6, 12 ], b: 100 }執行以下彙總操作(排序鍵為同級數組欄位):
db.coll.aggregate([ { $sort: {a: 1, b: 1} } ])由於文檔
_id: 1中欄位a和b為同級數組,構成並行數組,MongoDB無法完成排序導致報錯。若需對多個數組欄位進行複合排序,需確保排序欄位為嵌套數組或共用同一數組首碼,且資料模型中應避免在同級欄位中同時使用數群組類型。
Update操作更新
新增欄位的更新
自MongoDB 3.6起,通過更新操作添加的新欄位會按字典序(lexicographic order)追加。
例如,集合 coll 包含文檔:
{ _id: 0, x: 0 }執行更新操作添加兩個新欄位:
db.coll.update({_id: 0}, {$set: {b: 0, a: 0}})在3.6版本中,新欄位按字典序追加,更新後文檔為 {_id: 0, x: 0, a: 0, b: 0}。
在3.6之前的版本中,新欄位按更新文檔中的出現順序追加,結果為 {_id: 0, x: 0, b: 0, a: 0}。
與arrayFilters標識符衝突的欄位
自MongoDB 3.6起,若欄位名與arrayFilters的標識符文法(如 $[])衝突,則無法更新該欄位。
例如,集合 coll 包含文檔:
{ _id: 0, x: { "$[]": 0 } }執行更新操作:
db.coll.update({_id: 0}, {$set: {"x.$[]": 1}})在3.6之前的版本中,更新操作將執行成功。在3.6版本中,因欄位名 $[] 與arrayFilters文法衝突,將操作失敗。
此行為僅在 featureCompatibilityVersion(功能相容版本)設為3.6時生效。
對$pop操作符實施更嚴格的驗證
自MongoDB 3.6起,$pop 操作符的參數必須以下值:
-1:移除數組的第一個元素。1:移除數組的最後一個元素。
在3.6之前的版本中:
任意負數均可移除首元素。
任意非負數或非數值均可移除末尾元素。
移除$pushAll操作符
MongoDB 3.6移除了$pushAll 操作符(自2.4版起標記為棄用)。
請使用 $push + $each 操作符實現相同功能。樣本如下:
db.students.update(
{ name: "joe" },
{ $push: { scores: { $each: [ 90, 92, 85 ] } } }
)平台支援變更
MongoDB 3.6 停止對 Windows Server 2008 R2 及 Windows 7 之前版本的支援。
MongoDB 3.6 未針對 macOS 10.13 及更新版本採用的APFS(Apple檔案系統)進行測試,在此類環境中運行時可能存在相容性問題。
通用相容性更新說明
棄用MONGODB-CR認證機制
自MongoDB 3.6起,MONGODB-CR認證機制已被標記為棄用。若仍在使用MONGODB-CR認證模式,需立即升級至更安全的SCRAM認證。
仲裁節點(Arbiter)與優先順序
所有仲裁節點(Arbiter)的優先順序固定為 0。
棄用主從複製架構
MongoDB 3.6正式棄用主從複製(Master-Slave Replication)架構。
棄用WiredTiger儲存引擎的--nojournal選項
在3.6版本中,對使用WiredTiger儲存引擎的複本集成員,棄用--nojournal選項,以避免產生資料風險。
調整aggregate命令及返回結果
自MongoDB 3.6起,aggregate命令不再支援以單文檔形式返回結果。
執行aggregate命令時,必須指定以下選項之一:
cursor:以遊標形式返回結果(適用於巨量資料集)。explain:返回彙總管道的執行計畫分析。
建議您優先使用mongo shell中的db.collection.aggregate(),或對應驅動程式的等效方法。除非使用explain選項,否則這些方法預設返回遊標。
變更彙總中日期轉字串格式
自MongoDB 3.6版本起,在彙總運算式中將日期類型強制轉換為字串時,結果將包含毫秒級精度,並以字母 'Z' 結尾(表示UTC時區)。
樣本如下:
// Documents.
{_id: 0, d: ISODate("2017-10-18T20:04:27.978Z")}
{_id: 1, d: ISODate("2017-10-18T20:04:28.192Z")}
// Query.
db.coll.aggregate({$project: {d: {$toLower: "$d"}}})在MongoDB 3.6之前版本中,返回字串格式為 "2017-10-18t20:04:27" 和 "2017-10-18t20:04:28"。
在MongoDB 3.6及之後版本中,返回字串格式為 "2017-10-18t20:04:27.978z" 和 "2017-10-18t20:04:28.192z"(含毫秒及小寫'z')。
受影響的彙總操作符包括:
$concat$substr$substrBytes$substrCP$strcasecmp$toLower$toUpper
移除診斷記錄命令與選項
MongoDB 3.6移除了已棄用的 diagLogging 命令及 mongod --diaglog 選項。
替代方案:使用 mongoreplay 工具捕獲、回放及分析發送到MongoDB部署的命令。
validate操作變更
自MongoDB 3.6版本起,僅當執行完整驗證(full validation)時,validate 操作會強制觸發檢查點(checkpoint),將所有記憶體資料刷盤後再驗證磁碟資料。
在3.6之前的版本中,無論驗證模式如何,均強制觸發檢查點。
當您使用 validate 命令或 db.collection.validate() 方法時,需明確指定 {full: true} 以執行完整驗證。
索引名稱限制
自MongoDB 3.6版本起:
禁止建立名為
*的索引:無法在建立索引時指定名稱*。無法通過索引鍵刪除名為
*的索引:需直接通過索引名稱刪除。
在升級至MongoDB 3.6版本前,您需要:
刪除現有
*索引:在升級前手動刪除所有名為*的索引。重新命名索引:若需保留索引,需先刪除再重建並指定新名稱。
棄用選項
3.6.1版本變更。
棄用
snapshot查詢選項MMAPv1儲存引擎:改用
hint({ _id: 1 })確保查詢期間文檔不被重複返回(即使中間寫入導致文檔移動)。其他儲存引擎(如WiredTiger):改用
hint({ $natural: 1 })。
棄用
$isolated操作符替代方案:通過事務或調整讀寫關注(read concern)實現隔離性。
不向後相容的特性說明
以下MongoDB 3.6版本新特性需將featureCompatibilityVersion設為"3.6"後方可啟用:
集合UUID:每個集合擁有唯一識別碼。
$jsonSchema文檔驗證:支援JSON Schema格式的文檔結構校正。變更流(
Change Streams):即時監控資料變更事件。分區感知的從節點(Chunk Aware Secondaries):最佳化分區叢集中從節點的資料同步。
視圖定義、文檔驗證器及部分索引過濾器:若使用3.6新增的查詢功能,需啟用此配置。
會話與可重試寫入(Sessions & Retryable Writes):支援事務會話及寫入操作自動重試。
使用者與角色的認證限制(Authentication Restrictions):精細控制使用者權限。
featureCompatibilityVersion預設值如下:
全新部署的3.6版本:
"3.6"。從3.4升級的部署:
"3.4"(需手動通過setFeatureCompatibilityVersion設定為"3.6")。
您可以使用命令 db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } ) 查看當前featureCompatibilityVersion值。
若需從MongoDB 3.6版本降級至之前的版本,您必須清除所有不相容資料(包括與會話、變更流、UUID集合等相關的持久化資料)。