深入學習 Create 操作
Understanding "insert()" Methods
相較於 insertOne() 及 insertMany(),insert() 是比較不建議使用的方法。 三者差異如下:
- insertOne() 建立單筆資料,其值以花括號夾住傳入,回傳值包含 _id。
- insertMany() 建立多筆資料,其值以陣列傳入,回傳值包含 _id。
- insert() 建立單筆資料,將其值分散填入多個花括號再傳入,回傳值不包含 _id。
Working with Ordered Inserts
如以下範例所示,在 mongosh 以 insertMany() 建立多筆資料時,可手動輸入 _id。
此時四筆資料將依序寫入資料庫,但在寫入第三筆資料時,
由於其 _id 與第二筆寫入的資料重複,因此終端機會提示錯誤,第三筆以後的資料也不會寫入。
然而第一、第二筆資料並不會因為第三筆資料寫入失敗而 Rollback,因此 line 24 的查詢指令可取回兩筆資料。
db.numbers.insertMany([{_id: 1, num: 1}, {_id:2, num: 2}, {_id: 2, num: 3}, {_id:4, num: 4}])
Uncaught:
MongoBulkWriteError: E11000 duplicate key error collection: contactData.numbers index: _id_ dup key: { _id: 2 }
Result: BulkWriteResult {
insertedCount: 2,
matchedCount: 0,
modifiedCount: 0,
deletedCount: 0,
upsertedCount: 0,
upsertedIds: {},
insertedIds: { '0': 1, '1': 2, '2': 2, '3': 4 }
}
Write Errors: [
WriteError {
err: {
index: 2,
code: 11000,
errmsg: 'E11000 duplicate key error collection: contactData.numbers index: _id_ dup key: { _id: 2 }',
errInfo: undefined,
op: { _id: 2, num: 3 }
}
}
]
contactData> db.numbers.find()
[ { _id: 1, num: 1 }, { _id: 2, num: 2 } ]
選用無序插入
在插入指令中加入選項 {ordered: false} 可將預設的有序插入改成無序插入。
如以下範例,雖然第二、三筆資料的 _id 重複,但此操作會插入三筆資料。
db.numbers.insertMany([{_id: 1, num: 1}, {_id:2, num: 2},
{_id: 2, num: 3}, {_id:4, num: 4}], {ordered: false})
Understanding the "writeConcern"
The "writeConcern" in Practice
mongosh 輸入指令
$ db.users.insertOne({name: "Amy", age: 31}, {writeConcern: {w:0 }})
終端機顯示
{
acknowledged: false,
insertedId: ObjectId("64753e8ba141f7c513fa345c")
}
上述指令中,w:0 表示插入資料時不等待伺服器確認,因此回傳訊息顯示 acknowledged: false
然而回傳訊息中也顯示了 insertedId,可知資料有成功插入資料庫。
若將 w:0 改為 w:1 則是使用預設值,插入資料時會等待伺服器確認。
雖然 w:0 與 w:1 的耗時差距極短,但若是特別在乎耗時的應用情境,就可以考慮加入這項 writeConcern。
mongosh 輸入指令
$ db.users.insertOne({name: "Betty", age: 13}, {writeConcern: {w:1, j: true }})
終端機顯示
{
acknowledged: true,
insertedId: ObjectId("64754e27a141f7c513fa345d")
}
上述指令中,j:true 表示插入資料時需等待 journal 記錄完畢,當然這也會使操作多耗費一點時間。
在預設狀態下,j 選項為 false。
mongosh 輸入指令
$ db.users.insertOne({name: "Celeste", age: 24}, {writeConcern: {w:1, j: true, wtimeout: 200 }})
終端機顯示
{
acknowledged: true,
insertedId: ObjectId("647551d0a141f7c513fa345e")
}
上述指令中,wtimeout 選項可防止寫入操作無限期阻塞。
What is Atomicity?
如下圖所示,MongoDB 的原子性是 Document 層級。插入單筆資料時,只要 Document 內發生一個錯誤,就會使整個 Document 無法儲存。
insertMany() 與 insertOne() 的差異
$ db.collectionName.insertMany({key1: value1}, {key2: value2}, {key3: value3})
在插入多筆資料時,必須以 transaction 執行才能在發生錯誤時 Rollback。
假設你未應用 transaction 執行上述指令,且在寫入第二筆 Document 時發生錯誤,第一筆 Document 並不會 Rollback。
Multi-Document Transactions
When a single write operation (e.g. db.collection.updateMany()) modifies multiple documents, the modification of each document is atomic, but the operation as a whole is not atomic.
MongoDB 官方文件:Atomicity and Transactions
Importing Data
在進入 mongosh 以前執行下列指令,可從指定路徑匯入資料。
$ mongoimport fileName.json -d databaseName -c collectionName --jsonArray --drop
上述指令含意
- 將終端機目前所在路徑的特定檔案匯入 MongoDB
- --jsonArray 表示讀取 JSON 檔案內的所有元素。若不加入此副指令,則只會匯入一個元素。
- --drop 表示如果指定的 collection 存在,則將之刪除並重新匯入。