跳至主要内容

深入學習 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"

Write Concern

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 無法儲存。 MongoDB 的 Atomicity

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 存在,則將之刪除並重新匯入。