mongoose之bulkWrite操作使用實例
前言
在執行mongo操作時,有時候大傢會覺得力不從心,比如:要給大量的數據更新,但是各個數據更新的內容不一樣;需要批量創建大量數據; 以上操作,如果單純使用findIOneAndUpdate或者save,首先是非常耗時、其次使用瞭大量的資源;
那麼有沒有什麼好的方法去替代呢?
mongoose提供瞭bulkWrite批量操作防范,這個方法支持批量插入、更新和刪除;
當然,不會有人以為批量操作就不能單獨操作一條數據吧!
一: bulkWrite小小解釋
mongoose關於bulkWrite的原文:mongoosejs.com/docs/api.ht…
操作語法:
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。 |
關於ordered
- 如果為true,有序執行,按順序執行並在第一個錯誤處停止,遇到錯誤就停止執行後續的operations操作(後續的操作不會被執行)
- 如果為false,無序執行,為並行執行,如果遇到錯誤,會繼續執行在一個操作,直到所有操作成功或出錯;
綜上所述,個人建議使用時配置為無序執行;各位可以按需求使用,後續會具體說明各項操作及返回值
二:具體操作
insertOne
插入單個文檔到集合中;
db.collection.bulkWrite( [ { insertOne : { "document" : {} } }, { insertOne : { "document" : {} } } ] ,{ordered:fasle}) db.collection.bulkWrite( [ { insertOne : { "document" : {} } }, { insertOne : { "document" : {} } } ])
字段說明
insertOne.document
:需要插入的文檔信息,如果文檔不包含_id,則會自動生成;ordered
:選填,有序還是無序執行;
updateOne
updateOne 更新集合中 filter 匹配的單個文檔。如果匹配到多個文檔 updateOne 僅更新第一個匹配到的文檔;
db.collection.bulkWrite( [ { updateOne : { "filter" : {name:"bulkWrite6"}, "update" : {$set:{age:19}}, "upsert" :true } } ],{ordered:fasle} ) db.collection.bulkWrite( [ { updateOne : { "filter" : {name:"bulkWrite6"}, "update" : {$set:{age:19}},, "upsert" :true } } ] )
字段說明
updateOne.filter
:object,必填,匹配條件;updateOne.update
:object,必填,更新內容,可執行操作為:set、 set 、set、 unset 、$rename等等;updateOne.upsert
: boolean, 選填,默認為false,如果為true,則沒有匹配時插入一個新文檔;
updateMany
updateMany 更新集合中所有匹配到的文檔;
db.collection.bulkWrite( [ { updateMany : { "filter" : {name:"bulkWrite6"}, "update" : {$set:{age:19}}, "upsert" :true } } ],{ordered:fasle} ) db.collection.bulkWrite( [ { updateMany : { "filter" : {name:"bulkWrite6"}, "update" : {$set:{age:19}},, "upsert" :true } } ] )
字段說明
updateOne.filter
:object,必填,匹配條件;updateOne.update
:object,必填,更新內容,可執行操作為:set、 set 、set、 unset 、$rename等等;updateOne.upsert
: boolean, 選填,默認為false,如果為true,則插入一個文檔filter
deleteOne
deleteOne 刪除集合中 filter 匹配到的單個文檔。如果匹配到多個文檔 deleteOne 隻會刪除一個匹配到的文檔;
db.collection.bulkWrite([ { deleteOne : { "filter" : {age:19} } } ] )
字段說明
deleteOne.filter
:object,必填,刪除與此過濾器匹配的第一個文檔;
deleteMany
deleteMany 刪除集合中 filter 匹配到的所有文檔;
db.collection.bulkWrite([ { deleteMany : { "filter" : {age:19} } } ] )
字段說明
deleteMany.filter
:object,必填,刪除與此過濾器匹配的所有文檔;
replaceOne
replaceOne 替換集合中 filter 匹配到的單個文檔。如果匹配到多個文檔 replaceOne 隻會替換一個匹配到的文檔;
db.collection.bulkWrite([ { replaceOne : { "filter" :{age:19}, "replacement" : {age:20}, "upsert" :true } } ] )
字段說明
updateOne.filter
:object,必填,替換與此過濾器匹配的第一個文檔;updateOne.update
:object,必填,替換內容;updateOne.upsert
: boolean, 選填,默認為false,如果為true,如果沒有匹配的文檔,則插入一個文檔filter
三:優點
- 可以批量同時執行不同的操作,新增、修改、刪除;
- 執行速率比save、findOneAndUpdate等等快,因為,bulkWrite是在一個命令中向 MongoDB 服務器發送多個insertOne、updateOne、updateMany、replaceOne、 deleteOne等等的請求,這比發送多個獨立操作更快,因為bulkWrite()隻有一次往返 MongoDB,而每一次獨立操作都是一次往返的MongoDB。
四:以下需要註意
- ordered參數,由於bulkWrite中可以幾個操作同時混合使用,那麼,如果使用無序執行時,可能會造成deleteOne或deleteMany 刪除的文檔可能會變多或變少,具體取決於deleteOne或deleteMany 是在insertOne,updateOne,updateMany或replaceOne操作之前或之後的運行。
如下:
db.collection.bulkWrite( [ { insertOne : <document> }, { updateOne : <document> }, { updateMany : <document> }, { replaceOne : <document> }, { deleteOne : <document> }, { deleteMany : <document> } ], { ordered : false } )
- 更新(updateOne、updateMany)或替換(replaceOne)操作不能指定與原始文檔不同的 _id 值;
五:錯誤返回
錯誤返回值主要分為兩種,ordered的有序和無序執行的錯誤返回, 以下述插入為例,第一項、第四項和第五項是不存在的,第二項和第三項的_id是已存在的
有序執行錯誤
db.collection.bulkWrite( [ { insertOne: { document: { name: 'bulkWrite10' } } }, { insertOne: { document: { _id: '6321a77b06e79133d99b926c', name: 'bulkWrite6' } } }, { insertOne: { document: { _id: '63227cde0795b55523c0e8ac', name: 'bulkWrite7' } } }, { insertOne: { document: { name: 'bulkWrite11' } } }, { insertOne: { document: { name: 'bulkWrite12' } } } ], { ordered: true } );
有序執行錯誤,返回值中隻有一個錯誤的,但是insertedIds中index=2、3、4都沒有執行
{ "code": 11000, "writeErrors": [ { "code": 11000, "index": 1, "errmsg": "E11000 duplicate key error collection: test_one.users index: _id_ dup key: { _id: ObjectId('6321a77b06e79133d99b926c') }", "op": { "name": "bulkWrite6", "age": 0, "register_time": "2022-09-15T03:45:04.529Z", "remark": null, "vip": false, "address": null, "_id": "6321a77b06e79133d99b926c" } } ], "result": { "ok": 1, "writeErrors": [ { "code": 11000, "index": 1, "errmsg": "E11000 duplicate key error collection: test_one.users index: _id_ dup key: { _id: ObjectId('6321a77b06e79133d99b926c') }", "op": { "name": "bulkWrite6", "age": 0, "register_time": "2022-09-15T03:45:04.529Z", "remark": null, "vip": false, "address": null, "_id": "6321a77b06e79133d99b926c" } } ], "writeConcernErrors": [], "insertedIds": [ { "index": 0, "_id": "63229fc8afcdaac9bd268102" }, { "index": 1, "_id": "6321a77b06e79133d99b926c" }, { "index": 2, "_id": "63227cde0795b55523c0e8ac" }, { "index": 3, "_id": "63229fc8afcdaac9bd268105" }, { "index": 4, "_id": "63229fc8afcdaac9bd268106" } ], "nInserted": 1, "nUpserted": 0, "nMatched": 0, "nModified": 0, "nRemoved": 0, "upserted": [] } }
無序執行錯誤
db.collection.bulkWrite( [ { insertOne: { document: { name: 'bulkWrite10' } } }, { insertOne: { document: { _id: '6321a77b06e79133d99b926c', name: 'bulkWrite6' } } }, { insertOne: { document: { _id: '63227cde0795b55523c0e8ac', name: 'bulkWrite7' } } }, { insertOne: { document: { name: 'bulkWrite11' } } }, { insertOne: { document: { name: 'bulkWrite12' } } } ], { ordered: false } );
無序執行錯誤,返回值中有兩個報錯,三個插入成功
{ "code": 11000, "writeErrors": [ { "code": 11000, "index": 1, "errmsg": "E11000 duplicate key error collection: test_one.users index: _id_ dup key: { _id: ObjectId('6321a77b06e79133d99b926c') }", "op": { "name": "bulkWrite6", "age": 0, "register_time": "2022-09-15T03:47:51.976Z", "remark": null, "vip": false, "address": null, "_id": "6321a77b06e79133d99b926c" } }, { "code": 11000, "index": 2, "errmsg": "E11000 duplicate key error collection: test_one.users index: _id_ dup key: { _id: ObjectId('63227cde0795b55523c0e8ac') }", "op": { "name": "bulkWrite7", "age": 0, "register_time": "2022-09-15T03:47:51.976Z", "remark": null, "vip": false, "address": null, "_id": "63227cde0795b55523c0e8ac" } } ], "result": { "ok": 1, "writeErrors": [ { "code": 11000, "index": 1, "errmsg": "E11000 duplicate key error collection: test_one.users index: _id_ dup key: { _id: ObjectId('6321a77b06e79133d99b926c') }", "op": { "name": "bulkWrite6", "age": 0, "register_time": "2022-09-15T03:47:51.976Z", "remark": null, "vip": false, "address": null, "_id": "6321a77b06e79133d99b926c" } }, { "code": 11000, "index": 2, "errmsg": "E11000 duplicate key error collection: test_one.users index: _id_ dup key: { _id: ObjectId('63227cde0795b55523c0e8ac') }", "op": { "name": "bulkWrite7", "age": 0, "register_time": "2022-09-15T03:47:51.976Z", "remark": null, "vip": false, "address": null, "_id": "63227cde0795b55523c0e8ac" } } ], "writeConcernErrors": [], "insertedIds": [ { "index": 0, "_id": "6322a06b9145a56d3b23fabe" }, { "index": 1, "_id": "6321a77b06e79133d99b926c" }, { "index": 2, "_id": "63227cde0795b55523c0e8ac" }, { "index": 3, "_id": "6322a06b9145a56d3b23fac1" }, { "index": 4, "_id": "6322a06b9145a56d3b23fac2" } ], "nInserted": 3, "nUpserted": 0, "nMatched": 0, "nModified": 0, "nRemoved": 0, "upserted": [] } }
六:思考
個人經常使用bulkWrite的場景是:
- 定時更新數據,比如更新人員基本信息,因為每個人更新的內容都不相同;
- 刷數據,有些數據需要刪除、有些需要更新、有些需要新增;
bulkWrite是比save、update更為高級的寫法,希望大傢可以靈活運用。
引用
mongoose關於bulkWrite的原文:mongoosejs.com/docs/api.ht…
以上就是mongoose之bulkWrite操作使用實例的詳細內容,更多關於mongoose bulkWrite操作的資料請關註WalkonNet其它相關文章!