MongoDB 批量更新、批量新增、批量刪除、批量替換 —— bulkWrite操作忽略主鍵沖突


批量插入數據,主鍵沖突報錯,並繼續執行后面操作

ordered : <boolean> --false

定義

db.collection.bulkWrite()

提供可控執行順序的批量寫操作。

語法格式如下:

1
2
3
4
5
6
7
db.collection.bulkWrite(
    [ <operation 1>, <operation 2>, ... ],
    {
       writeConcern : <document>,
       ordered : <boolean>
    }
)
參數 類型 描述
operations array bulkWrite() 寫操作的數組。支持操作:insertOne、updateOne、updateMany、deleteOne、deleteMany、replaceOne
writeConcern document 可選, write concern 文檔,省略則使用默認的 write concern。
ordered boolean 可選,表示mongod實例有序還是無序執行操作。默認值true。

方法返回值:

  • 操作基於 write concern 運行則 acknowledged 值為true,如果禁用 write concern 運行則 acknowledged 值為false。禁用writeConcern寫法{writeConcern:{w:-1}}

  • 每一個寫操作數。

  • 成功 inserted 或 upserted文檔的 _id 的組數。

 db.test.bulkWrite([{insertOne:{"document":{"name":"xiaoxu","age":10}},{insertOne:{"document":{"name":"xiaoxu","age":10}},{insertOne:{"document":{"name":"xiaoliu","age":20}},{writeConcern:{w:-1},ordered:false}}])

這樣則可以忽略主鍵沖突,寫入兩條數據。

行為

bulkWrite() 接收一個寫操作的數組然后執行它們中的每一個。默認是有序的執行。

 

寫操作

insertOne

插入單個文檔到集合中。

1
2
3
db.collection.bulkWrite( [
    { insertOne : {  "document"  : <document> } }
] )

updateOne 及 updateMany

updateOne 更新集合中 filter 匹配的單個文檔。如果匹配到多個文檔 updateOne 僅更新第一個匹配到的文檔。

1
2
3
4
5
6
7
8
9
db.collection.bulkWrite( [
    { updateOne :
       {
          "filter"  : <document>,
          "update"  : <document>,
          "upsert"  : <boolean>
       }
    }
] )

updateMany 更新集合中所有匹配到的文檔。

1
2
3
4
5
6
7
8
9
db.collection.bulkWrite( [
    { updateMany :
       {
          "filter"  : <document>,
          "update"  : <document>,
          "upsert"  : <boolean>
       }
    }
] )

對字段的更新操作例如 $set 、$unset 、$rename等。

默認情況 upsert 為 false。

replaceOne

replaceOne 替換集合中 filter 匹配到的單個文檔。如果匹配到多個文檔 replaceOne 只會替換一個匹配到的文檔。

1
2
3
4
5
6
7
8
9
db.collection.bulkWrite([
    { replaceOne :
       {
          "filter"  : <document>,
          "replacement"  : <document>,
          "upsert"  : <boolean>
       }
    }
] )

replacement 字段中不能包含 update 操作。

默認情況 upsert 為 false。

deleteOne 及 deleteMany

deleteOne 刪除集合中 filter 匹配到的單個文檔。如果匹配到多個文檔 deleteOne 只會刪除一個匹配到的文檔。

1
2
3
db.collection.bulkWrite([
    { deleteOne :  {  "filter"  : <document> } }
] )

deleteMany 刪除集合中 filter 匹配到的所有文檔。

1
2
3
db.collection.bulkWrite([
    { deleteMany :  {  "filter"  : <document> } }
] )

 

_id 字段

如果文檔未指定 _id 字段,則mongod會在 insert 或 upsert 文檔之前添加 _id 字段並指定唯一的ObjectId。 大多數驅動程序會創建一個ObjectId並插入到 _id 字段,但如果驅動程序或應用程序沒有,mongod將創建並填充 _id。

如果文檔包含 _id 字段,則 _id 值在集合中必須是唯一的,以避免重復鍵錯誤。

更新或替換操作不能指定與原始文檔不同的 _id 值。

 

執行操作

ordered 參數指定  bulkWrite() 是否有序執行,默認情況下是有序執行。

含有6個操作的 bulkWrite()  代碼如下:

1
2
3
4
5
6
7
8
9
10
db.collection.bulkWrite(
    [
       { insertOne : <document> },
       { updateOne : <document> },
       { updateMany : <document> },
       { replaceOne : <document> },
       { deleteOne : <document> },
       { deleteMany : <document> }
    ]
)

默認情況下 ordered : true ,每個操作將會有序的執行,從第一個insertOne 到最后一個deleteMany 順序執行。

應用程序不依賴操作執行順序是,可以設置 ordered 為 false ,此時mongod 會重新排序操作來提高性能。

含有6個操作無序的 bulkWrite()  代碼如下:

1
2
3
4
5
6
7
8
9
10
11
db.collection.bulkWrite(
    [
       { insertOne : <document> },
       { updateOne : <document> },
       { updateMany : <document> },
       { replaceOne : <document> },
       { deleteOne : <document> },
       { deleteMany : <document> }
    ],
    { ordered :  false  }
)

對於ordered:false,操作結果可能會有所不同。 例如,deleteOne或deleteMany 刪除的文檔可能會變多或變少,具體取決於deleteOne或deleteMany 是在insertOne,updateOne,updateMany或replaceOne操作之前或之后的運行。

每組操作最多可以有1000次操作。 如果一個組超過此限制,MongoDB會將該組划分為1000或更小的組。 例如,如果隊列包含2000個操作,MongoDB將創建2個組,每個組具有1000個操作。

大小和分組機制是內部的執行細節,在將來的版本中可能會有所變化。

在分片集合上執行有序操作通常比執行無序操作慢,因為對於有序,每個操作必須等待上一個操作完成。

 

固定集合(Capped Collections)

bulkWrite() 寫操作在固定集合上使用有所限制。

  • updateOne 和 updateMany 更新時增加了被修改文檔的大小將會拋出 WriteError

  • replaceOne 操作替換的文檔比之前的文檔大會拋出 WriteError

  • deleteOne 和 deleteMany 操作在固定集合上會拋出 WriteError

 

操作處理(Error Handling)

bulkWrite() 在錯誤發生時會拋出 BulkWriteError 異常。

排除Write Concern錯誤,有序操作在發生錯誤后停止,及無序操作繼續處理隊列中的剩余寫入操作。

Write Concern 錯誤顯示在 writeConcernErrors字段中,而所有其他錯誤都顯示在writeErrors字段中。 如果遇到錯誤,則顯示成功寫入操作的數量而不是插入的_id值。 有序操作顯示遇到的單個錯誤,而無序操作顯示數組中的每個錯誤。

 

實例

批量寫

characters 集合包含以下文檔:

1
2
3
"_id"  : 1,  "char"  "Brisbane" "class"  "monk" "lvl"  : 4 },
"_id"  : 2,  "char"  "Eldon" "class"  "alchemist" "lvl"  : 3 },
"_id"  : 3,  "char"  "Meldane" "class"  "ranger" "lvl"  : 3 }

bulkWrite() 在集合上執行批量操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
try  {
    db.characters.bulkWrite(
       [
          { insertOne :
             {
                "document"  :
                {
                   "_id"  : 4,  "char"  "Dithras" "class"  "barbarian" "lvl"  : 4
                }
             }
          },
          { insertOne :
             {
                "document"  :
                {
                   "_id"  : 5,  "char"  "Taeln" "class"  "fighter" "lvl"  : 3
                }
             }
          },
          { updateOne :
             {
                "filter"  : {  "char"  "Eldon"  },
                "update"  : { $set : {  "status"  "Critical Injury"  } }
             }
          },
          { deleteOne :
             "filter"  : {  "char"  "Brisbane" } }
          },
          { replaceOne :
             {
                "filter"  : {  "char"  "Meldane"  },
                "replacement"  : {  "char"  "Tanys" "class"  "oracle" "lvl"  : 4 }
             }
          }
       ]
    );
}
catch  (e) {
    print(e);
}

操作結果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
    "acknowledged"  true ,
    "deletedCount"  : 1,
    "insertedCount"  : 2,
    "matchedCount"  : 2,
    "upsertedCount"  : 0,
    "insertedIds"  : {
       "0"  : 4,
       "1"  : 5
    },
    "upsertedIds"  : {
 
    }
}

如果 第二個 insertOne 操作的 _id 是集合中已經存在的,則會拋出以下錯誤:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
BulkWriteError({
    "writeErrors"  : [
       {
          "index"  : 0,
          "code"  : 11000,
          "errmsg"  "E11000 duplicate key error collection: guidebook.characters index: _id_ dup key: { : 4 }" ,
          "op"  : {
             "_id"  : 5,
             "char"  "Taeln"
          }
       }
    ],
    "writeConcernErrors"  : [ ],
    "nInserted"  : 1,
    "nUpserted"  : 0,
    "nMatched"  : 0,
    "nModified"  : 0,
    "nRemoved"  : 0,
    "upserted"  : [ ]
})

默認情況下 ordered 為 true, 順序執行時遇到錯誤就停止執行(后續的操作不會被執行)。

無序批量寫

characters 集合包含以下文檔:

1
2
3
"_id"  : 1,  "char"  "Brisbane" "class"  "monk" "lvl"  : 4 },
"_id"  : 2,  "char"  "Eldon" "class"  "alchemist" "lvl"  : 3 },
"_id"  : 3,  "char"  "Meldane" "class"  "ranger" "lvl"  : 3 }

bulkWrite() 在集合上執行批量操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
try  {
    db.characters.bulkWrite(
          [
             { insertOne :
                {
                   "document"  :
                   {
                      "_id"  : 4,  "char"  "Dithras" "class"  "barbarian" "lvl"  : 4
                   }
                }
             },
             { insertOne :
                {
                   "document"  :
                      {
                         "_id"  : 4,  "char"  "Taeln" "class"  "fighter" "lvl"  : 3
                      }
                }
             },
             { updateOne :
                {
                   "filter"  : {  "char"  "Eldon"  },
                   "update"  : { $set : {  "status"  "Critical Injury"  } }
                }
             },
             { deleteOne :
                "filter"  : {  "char"  "Brisbane" } }
             },
             { replaceOne :
                {
                   "filter"  : {  "char"  "Meldane"  },
                   "replacement"  : {  "char"  "Tanys" "class"  "oracle" "lvl"  : 4 }
                }
             }
          ],
             { ordered :  false  }
       );
    }
    catch  (e) {
    print(e);
}

操作結果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
BulkWriteError({
    "writeErrors"  : [
       {
          "index"  : 0,
          "code"  : 11000,
          "errmsg"  "E11000 duplicate key error collection: guidebook.characters index: _id_ dup key: { : 4 }" ,
          "op"  : {
             "_id"  : 4,
             "char"  "Taeln"
          }
       }
    ],
    "writeConcernErrors"  : [ ],
    "nInserted"  : 1,
    "nUpserted"  : 0,
    "nMatched"  : 2,
    "nModified"  : 2,
    "nRemoved"  : 1,
    "upserted"  : [ ]
})

無序操作,盡管操作過程中出現錯誤,剩余的操作也不會就此終止執行。

基於 Write Concern 的批量寫

enemies 集合包含以下文檔:

1
2
3
4
"_id"  : 1,  "char"  "goblin" "rating"  : 1,  "encounter"  : 0.24 },
"_id"  : 2,  "char"  "hobgoblin" "rating"  : 1.5,  "encounter"  : 0.30 },
"_id"  : 3,  "char"  "ogre" "rating"  : 3,  "encounter"  : 0.2 },
"_id"  : 4,  "char"  "ogre berserker"  "rating"  : 3.5,  "encounter"  : 0.12}

以下使用 write concern 值為 "majority" 及 timeout 為 100 毫秒來執行批量寫操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
try  {
    db.enemies.bulkWrite(
       [
          { updateMany :
             {
                "filter"  : {  "rating"  : { $gte : 3} },
                "update"  : { $inc : {  "encounter"  : 0.1 } }
             },
 
          },
          { updateMany :
             {
                "filter"  : {  "rating"  : { $lt : 2} },
                "update"  : { $inc : {  "encounter"  : -0.25 } }
             },
          },
          { deleteMany : {  "filter"  : {  "encounter"  { $lt : 0 } } } },
          { insertOne :
             {
                "document"  :
                   {
                      "_id"  :5,  "char"  "ogrekin"  "rating"  : 2,  "encounter"  : 0.31
                   }
             }
          }
       ],
       { writeConcern : { w :  "majority" , wtimeout : 100 } }
    );
}
catch  (e) {
    print(e);
}

如果副本集中所有必需節點確認寫入操作所需的總時間大於wtimeout,則在wtimeout 時間過去時將顯示以下writeConcernError。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
BulkWriteError({
    "writeErrors"  : [ ],
    "writeConcernErrors"  : [
       {
          "code"  : 64,
          "errInfo"  : {
             "wtimeout"  true
          },
          "errmsg"  "waiting for replication timed out"
       }
    ],
    "nInserted"  : 1,
    "nUpserted"  : 0,
    "nMatched"  : 4,
    "nModified"  : 4,
    "nRemoved"  : 1,
    "upserted"  : [ ]
    })

結果集顯示執行的操作,因為writeConcernErrors錯誤不是任何寫入操作失敗的標志。

 

https://docs.mongodb.com/v3.4/reference/method/db.collection.bulkWrite


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM