1. 程式人生 > 其它 >【翻譯】MongoDB指南/CRUD操作(二)

【翻譯】MongoDB指南/CRUD操作(二)

【原文地址】https://docs.mongodb.com/manual/

MongoDB CRUD操作(二)

主要內容:

更新文件,刪除文件,批量寫操作,SQL與MongoDB對映圖,讀隔離(讀關注),寫確認(寫關注)

1 更新文件

1.1 更新

MongoDB提供下列方法用於更新一個集合

db.collection.updateOne()

更新使用指定過濾器匹配到的文件,即使過濾器匹配到多個文件,也只會更新一個文件。 3.2版本新增特性。

db.collection.updateMany()

更新使用指定過濾器匹配到的所有文件。 3.2版本新增特性。

db.collection.replaceOne()

替換使用指定過濾器匹配到的文件,即使過濾器匹配到多個文件,也只會更新一個文件。 3.2版本新增特性。

db.collection.update()

更新或者替換一個使用指定過濾器匹配到的文件,或者更新使用指定過濾器匹配到的所有文件。 預設只更新一個文件。為了更新多個文件,請使用multi 選項。

上述方法接受以下引數:

  • 過濾器文件,確定要更新哪些文件。這些過濾器與查詢操作中使用的過濾器有相同的句法規則。
    •   查詢過濾器文件,使用表示式<field>:<value>指定相等條件,找出所有欄位<field>的值為<value>的文件:

        { <field1>: <value1>, ... }

  •   查詢過濾器文件,可使用查詢操作符指定條件:

        { <field1>: { <operator1>: <value1> }, ... }

  • 指定了更新內容的更新文件;或一個替換的文件,替換掉匹配到的文件而保持_id欄位不變。
  • 一個選項文件。

1.2 行為

原子性

MongoDB 中寫操作在單文件級別具有原子性。

_id欄位

文件一旦建立,_id欄位值就固定了,不能被更新,也不能用一個_id欄位值與原文件不同的文件來替換原文件。

文件大小

當執行更新操作時,導致文件變大並超出已分配的大小時,更新操作會在磁碟上重新定位檔案。

欄位順序

MongoDB 保持欄位寫入時的順序,除非遇到下列情況:

  • _id欄位總是處在首位。
  • 更新的時候對某一個或某些欄位重新命名可能導致欄位順序變更

2.6版本中的變化:從2.6版本開始,MongoDB 儘可能地保持欄位寫入時的順序,但之前的版本並不是這樣的。

Upsert 選項

如果db.collection.update(), db.collection.updateOne(), db.collection.updateMany(), 或者db.collection.replaceOne()包括

“upsert : true”並且使用指定的過濾器沒有匹配到任何文件,那麼此操作將會建立一個新文件並插入資料庫。如果匹配到文件,那麼此操作將修改或者替換匹配到的一個或多個文件。

1.3示例集合

本頁的例子在mongo shell中使用db.collection.find() 方法。在mongo shell中,如果沒有將遊標賦給一個var型別的變數,那麼遊標將會自動迭代20次以列印結果集中的前20個文件。

mongo shell中執行下面的語句,將資料灌入users 集合。

db.users.insertMany(
   [
     {
       _id: 1,
       name: "sue",
       age: 19,
       type: 1,
       status: "P",
       favorites: { artist: "Picasso", food: "pizza" },
       finished: [ 17, 3 ],
       badges: [ "blue", "black" ],
       points: [
          { points: 85, bonus: 20 },
          { points: 85, bonus: 10 }
       ]
     },
     {
       _id: 2,
       name: "bob",
       age: 42,
       type: 1,
       status: "A",
       favorites: { artist: "Miro", food: "meringue" },
       finished: [ 11, 25 ],
       badges: [ "green" ],
       points: [
          { points: 85, bonus: 20 },
          { points: 64, bonus: 12 }
       ]
     },
     {
       _id: 3,
       name: "ahn",
       age: 22,
       type: 2,
       status: "A",
       favorites: { artist: "Cassatt", food: "cake" },
       finished: [ 6 ],
       badges: [ "blue", "Picasso" ],
       points: [
          { points: 81, bonus: 8 },
          { points: 55, bonus: 20 }
       ]
     },
     {
       _id: 4,
       name: "xi",
       age: 34,
       type: 2,
       status: "D",
       favorites: { artist: "Chagall", food: "chocolate" },
       finished: [ 5, 11 ],
       badges: [ "Picasso", "black" ],
       points: [
          { points: 53, bonus: 15 },
          { points: 51, bonus: 15 }
       ]
     },
     {
       _id: 5,
       name: "xyz",
       age: 23,
       type: 2,
       status: "D",
       favorites: { artist: "Noguchi", food: "nougat" },
       finished: [ 14, 6 ],
       badges: [ "orange" ],
       points: [
          { points: 71, bonus: 20 }
       ]
     },
     {
       _id: 6,
       name: "abc",
       age: 43,
       type: 1,
       status: "A",
       favorites: { food: "pizza", artist: "Picasso" },
       finished: [ 18, 12 ],
       badges: [ "black", "blue" ],
       points: [
          { points: 78, bonus: 8 },
          { points: 57, bonus: 7 }
       ]
     }
   ]
)

1.4 更新一個文件的指定欄位

為了改變欄位,MongoDB提供了更新操作符,例如,使用$set修改欄位值。

更新文件的格式為:

{
   <update operator>: { <field1>: <value1>, ... },
   <update operator>: { <field2>: <value2>, ... },
   ...
}

有些更新操作符會在被更新欄位不存在的情況下建立該欄位,如 $set

db.collection.updateOne()

3.2版本新增

下面的例子演示使用db.collection.updateOne()方法和匹配條件favorites.artist等於“Picasso”,更新匹配出的多個文件中的第一個:

  • 使用操作符$set將欄位favorites.food的值修改為“pie”並將欄位的型別值改為3.
  • 使用操作符 $currentDate將欄位lastModified 的值更改為當前時間。如果欄位lastModified 不存在,$currentDate 會建立此欄位。
db.users.updateOne(
   { "favorites.artist": "Picasso" },
   {
     $set: { "favorites.food": "pie", type: 3 },
     $currentDate: { lastModified: true }
   }
)

db.collection.updateMany()

3.2版本新增

下面的例子演示使用db.collection.updateMany()方法和匹配條件favorites.artist等於“Picasso”,更新匹配出的所有文件:

  • 使用操作符$set將欄位favorites.food的值修改為“pie”並將欄位的型別值改為3.
  • 使用操作符 $currentDate將欄位lastModified 的值更改為當前時間。如果欄位lastModified不存在,$currentDate會建立此欄位。
db.users.updateMany(
   { "favorites.artist": "Picasso" },
   {
     $set: { "favorites.artist": "Pisanello", type: 3 },
     $currentDate: { lastModified: true }
   })

Db.collection.update()

下面的例子演示使用db.collection.updateOne()方法和匹配條件favorites.artist等於“Picasso”,更新匹配出的多個文件中的第一個:

  • 使用操作符$set將欄位favorites.food的值修改為“pie”並將欄位的型別值改為0.
  • 使用操作符 $currentDate將欄位lastModified 的值更改為當前時間。如果欄位lastModified 不存在,$currentDate 會建立此欄位。
db.users.update(
   { "favorites.artist": "Pisanello" },
   {
     $set: { "favorites.food": "pizza", type: 0,  },
     $currentDate: { lastModified: true }
   })

使用db.collection.update()方法和multi: true 選項更新多個文件

db.users.update(
   { "favorites.artist": "Pisanello" },
   {
     $set: { "favorites.food": "pizza", type: 0,  },
     $currentDate: { lastModified: true }
   },
   { multi: true })

1.5 替換文件

為了替換一個文件中除_id欄位以外的所有內容,將一個新文件作為db.collection.replaceOne()db.collection.update()的第二個引數進行傳遞。替換文件必須由<field> : <value>組成。

替換文件可以包含不同於原文件的欄位。因為_id欄位是不變的,所以替換文件中的_id欄位可以省略,如果替換文件中包含_id欄位,那麼替換文件的

_id欄位值必須與原文件相同。

db.collection.replaceOne

下面的例子演示了使用db.collection.replaceOne()方法和過濾條件條件為name 等於"abc" ,將集合users 中匹配到的第一個文件替換為一個新文件。

db.users.replaceOne(
   { name: "abc" },
   { name: "amy", age: 34, type: 2, status: "P", favorites: { "artist": "Dali", food: "donuts" } })

db.collection.update

下面的例子演示了使用db.collection.update()方法和過濾條件為name 等於"xyz" ,將集合users 中匹配到的第一個文件替換為一個新文件。

db.users.update(
   { name: "xyz" },
   { name: "mee", age: 25, type: 1, status: "A", favorites: { "artist": "Matisse", food: "mango" } })

其他方法

下面列舉了刪除文件的其他方法:

寫確認

對於寫確認,可以為寫操作指定要求的確認級別,具體參見 Write Concern

2 刪除文件

2.1 刪除方法

MongoDB提供下列方法刪除集合中的文件。

db.collection.remove()

刪除使用指定過濾器匹配到的一個或全部文件

db.collection.deleteOne()

至多刪除一個文件,即使使用指定過濾器匹配到多個文件。 3.2版本中新增

db.collection.deleteMany()

刪除匹配到的所有文件。 3.2版本中新增

你可以使用準則、過濾器確定要刪除的文件。這些過濾器與讀操作所使用的過濾器具有相同的語法規則。

  • 查詢過濾器文件使用<field>:<value>指定相等條件,篩選出所有欄位<field>的值為<value>的文件:
    { <field1>: <value1>, ... }
  • 查詢過濾器文件可以使用查詢操作符指定匹配條件:
    { <field1>: { <operator1>: <value1> }, ... }

2.2 刪除行為

索引

執行刪除操作時,即使刪除一個集合中的全部文件,也不會刪除索引。

原子性

MongoDB中所有寫操作在單文件級別具有原子性。

2.3示例集合

本頁提供了在mongo shell中使用刪除操作的例子。在mongo shell中執行下面語句,向集合users 中灌入資料。

注:

如果待插入文件的_id欄位值與集合已有文件_id欄位值相同,那麼在插入資料前要先將集合刪除(db.users.drop())。

db.users.insertMany(
  [
     {
       _id: 1,
       name: "sue",
       age: 19,
       type: 1,
       status: "P",
       favorites: { artist: "Picasso", food: "pizza" },
       finished: [ 17, 3 ],
       badges: [ "blue", "black" ],
       points: [
          { points: 85, bonus: 20 },
          { points: 85, bonus: 10 }
       ]
     },
     {
       _id: 2,
       name: "bob",
       age: 42,
       type: 1,
       status: "A",
       favorites: { artist: "Miro", food: "meringue" },
       finished: [ 11, 25 ],
       badges: [ "green" ],
       points: [
          { points: 85, bonus: 20 },
          { points: 64, bonus: 12 }
       ]
     },
     {
       _id: 3,
       name: "ahn",
       age: 22,
       type: 2,
       status: "A",
       favorites: { artist: "Cassatt", food: "cake" },
       finished: [ 6 ],
       badges: [ "blue", "red" ],
       points: [
          { points: 81, bonus: 8 },
          { points: 55, bonus: 20 }
       ]
     },
     {
       _id: 4,
       name: "xi",
       age: 34,
       type: 2,
       status: "D",
       favorites: { artist: "Chagall", food: "chocolate" },
       finished: [ 5, 11 ],
       badges: [ "red", "black" ],
       points: [
          { points: 53, bonus: 15 },
          { points: 51, bonus: 15 }
       ]
     },
     {
       _id: 5,
       name: "xyz",
       age: 23,
       type: 2,
       status: "D",
       favorites: { artist: "Noguchi", food: "nougat" },
       finished: [ 14, 6 ],
       badges: [ "orange" ],
       points: [
          { points: 71, bonus: 20 }
       ]
     },
     {
       _id: 6,
       name: "abc",
       age: 43,
       type: 1,
       status: "A",
       favorites: { food: "pizza", artist: "Picasso" },
       finished: [ 18, 12 ],
       badges: [ "black", "blue" ],
       points: [
          { points: 78, bonus: 8 },
          { points: 57, bonus: 7 }
       ]
     }
  ])

2.4刪除所有文件

為了刪除全部文件,使用db.collection.deleteMany()db.collection.remove()方法並將空過濾器文件{}傳給方法。

db.collection.deleteMany()

例如使用db.collection.deleteMany()方法刪除users 集合中所有文件:

db.users.deleteMany({})

返回結果文件中包含操作狀態:

{ "acknowledged" : true, "deletedCount" : 7 }

db.collection.remove()

或者使用db.collection.remove() 方法來刪除所有文件:

db.users.remove({})

為了刪除一個集合中的所有文件,db.collection.drop() 方法或許更高效;使用db.collection.drop() 方法刪除集合中的所有文件及其索引,然後重新建立集合和索引。

3.5刪除匹配到的所有文件

為了刪除所有匹配到的文件,傳遞一個過濾器給db.collection.deleteMany()db.collection.remove()方法。

db.collection.deleteMany()

例如,使用db.collection.deleteMany() 方法刪除users 集合中status 欄位值等於“A”的文件

db.users.deleteMany({ status : "A" })

返回結果:

{ "acknowledged" : true, "deletedCount" : 3 }

db.collection.remove()

或者使用db.collection.remove()方法刪除users 集合中status 欄位值等於“P”的文件

db.users.remove( { status : "P" } )

對於大的刪除操作,先將想保留的文件拷貝到新的集合中,然後使用db.collection.drop() 將原來的集合刪除,這種方法或許更高效。

2.6 僅刪除匹配到的文件中的一個

即使匹配到了多個文件,也只刪除其中的一個,使用db.collection.deleteOne() 方法,或者使用db.collection.remove()方法和使用<justOne>引數並將其設定為true或1 。

db.collection.deleteOne()

例如,使用db.collection.deleteOne() 刪除集合中status欄位值為“D”的文件中的第一個:

db.users.deleteOne( { status: "D" } )

db.collection.remove()

或者使用db.collection.remove()方法刪除users 集合中status 欄位值等於“D”的文件中的第一個:

db.users.remove( { status: "D" }, 1)

其他方法:

  • db.collection.findOneAndDelete():該方法提供了sort選項,sort選項可以刪除按指定順序排序的文件中的第一個。
  • db.collection.findOneAndModify():該方法提供了sort選項,sort選項可以刪除按指定順序排序的文件中的第一個。
  • db.collection.bulkWrite()

2.7 寫確認

對於寫確認,可以為寫操作指定需要的確認級別,具體參見 Write Concern

3 批量寫入操作

3.1 概要

MongoDB客戶端具有執行批量寫的能力。批量寫操作只會影響一個集合。MongoDB由應用程式決定可接受的批量寫操作安全級別。

3.2版本中新增:

db.collection.bulkWrite()方法提供了批量插入、更新、刪除。使用db.collection.insertMany()方法也可批量插入。

3.2排序與非排序操作

可以批量寫入一批已排序或未排序的文件。

對於有序的操作列表,MongoDB 按順序執行操作。如果在執行一個寫操作時發生錯誤,MongoDB 將會返回而不處理列表中剩下的操作。

對於無序的操作列表,MongoDB 並行地執行操作,但這種行為是無保障的。如果在執行一個寫操作時發生錯誤,MongoDB 將會繼續執行列表中剩下的操作。

MongoDB處理有序列表的速度比處理無序列表的速度要慢,因為處理有序列表時,每一個操作都要等待前一個操作執行完畢。

bulkWrite()方法預設依序執行操作。在選項文件中設定ordered : false,可以按無序方式執行。

3.3 bulkWrite()

bulkWrite()支援下列寫操作:

每個寫操作作為陣列中的一個文件被傳遞給bulkWrite()

例如,下面執行多個寫操作:

集合characters包含下面的文件:

{ "_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() 方法執行多個操作:

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);}

操作返回結果為:

{
   "acknowledged" : true,
   "deletedCount" : 1,
   "insertedCount" : 2,
   "matchedCount" : 2,
   "upsertedCount" : 0,
   "insertedIds" : {
      "0" : 4,
      "1" : 5
   },
   "upsertedIds" : {
   }}

3.4文件批量插入一個分片集策略

大塊插入操作,包括初始資料插入和常規資料匯入,都能影響分片叢集的效能。對於大塊的插入操作,考慮下面的策略:

集合預裂(Pre-Split the Collection)

如果分片集合是空的,那麼集合僅有一個初始塊,這一塊駐留在一片中。然後,MongoDB必須花時間來接收資料,建立分片,並將多個塊分佈到可用的片上。為了避免降低效能,你可以提前對一個集合分片。

無序寫入

為了改進寫入分片叢集的效能,將 bulkWrite()方法的選項引數ordered 設定為false。mongos 將會試著同時寫多片。

避免單調調節

如果插入文件的同時片鍵單調遞增,所有已插入的資料都會跑到集合的最後一塊,這總在一片上發生。因此叢集的插入容量永遠都不會超過一片的插入容量。

如果插入的量比一片所能處理的最大量還大,並且不能避免片鍵隨著插入操作而增大,那麼考慮按下面的策略修改你的應用程式:

  • 修改片鍵的二進位制位元數,這保留了資訊,同時也避免了插入順序與增加值序列關聯。
  • 交換第一個和最後一個16位元的詞來調整插入。

例如,下面的C++程式碼,交換BSON ObjectIds頭與尾16位元單詞,使其不再單調增加。

using namespace mongo;
OID make_an_id() {
  OID x = OID::gen();
  const unsigned char *p = x.getData();
  swap( (unsigned short&) p[0], (unsigned short&) p[10] );
  return x;
}
void foo() {
  // create an object
  BSONObj o = BSON( "_id" << make_an_id() << "x" << 3 << "name" << "jane" );
  // now we may insert o into a sharded collection
}

4  SQL與MongoDB對映圖

4.1術語和概念

下表展示了SQL與MongoDB的術語和概念對應關係

SQL Terms/Concepts

MongoDB Terms/Concepts

database(資料庫)

database(資料庫)

table(表)

collection(集合)

row(行)

document or BSON document(文件或BSON文件)

column(列)

field(欄位)

index(索引)

index(索引)

table joins(錶鏈接)

embedded documents and linking(嵌入式文件和連線)

primary key(主鍵) 指定唯一的一列或幾列做主鍵

primary key(主鍵) 在MongoDB中,主鍵被自動設定為_id欄位。

aggregation (聚集操作)(例如group by)

aggregation pipeline(聚集管道)

4.2可執行程式

下面的表格列舉了目前資料庫可執行程式與MongoDB可執行程式的對照。

此表並未列舉全。

MongoDB

MySQL

Oracle

Informix

DB2

資料庫伺服器

mongod

mysqld

oracle

IDS

DB2 Server

資料庫客戶端

mongo

mysql

sqlplus

DB-Access

DB2 Client

4.3例子

下面列出了SQL語句與MongoDB語句的對應關係。假設有如下的條件:

SQL語句中的表名為users。

MongoDB 中集合的名稱為users並且包含下面的文件模型:

{
  _id: ObjectId("509a8fb2f3f4948bd2f983a0"),
  user_id: "abc123",
  age: 55,
  status: 'A'
}

建立和更改

下面展示了表級操作對應關係。

SQL模式語句

MongoDB模式語句

CREATE TABLE users (     id MEDIUMINT NOT NULL         AUTO_INCREMENT,     user_id Varchar(30),     age Number,     status char(1), PRIMARY KEY (id) )

第一次執行insert() 操作會隱式建立集合。 如果沒有指定_id欄位,主鍵_id被自動新增. db.users.insert( {    user_id: "abc123",    age: 55,    status: "A" } ) 也可顯示建立集合: db.createCollection("users")

ALTER TABLE users ADD join_date DATETIME

集合不會描述和強制文件的結構;在集合這一級無文件結構的改變。 但在文件級, 可使用update()操作和 $set操作符向現有文件中新增欄位。 db.users.update( { },     { $set: { join_date: new Date() } },     { multi: true } )

ALTER TABLE users DROP COLUMN join_date

集合不會描述和強制文件的結構;在集合這一級無文件結構的改變。 但在文件級, 可使用update()操作和  $unset操作符刪除文件中的欄位。 db.users.update( { },     { $unset: { join_date: "" } },       { multi: true } )

CREATE INDEX idx_user_id_asc ON users(user_id)

db.users.createIndex( { user_id: 1 } )

CREATE INDEX     idx_user_id_asc_age_desc ON users(user_id, age DESC)

db.users.createIndex( { user_id: 1, age: -1 } )

DROP TABLE users

db.users.drop()

插入

下表展示了插入操作的對應關係

SQL插入語句

MongoDB insert() 語句

INSERT INTO users(user_id,age,status) VALUES ("bcd001",45,"A")

db.users.insert(   { user_id: "bcd001", age: 45, status: "A" })

查詢

下表展示了查詢操作的對應關係

注:

find() 方法的執行結果返回文件中總是包含_id欄位,除非通過投影器(projection)排除此欄位。考慮到這一點,下面的SQL語句可能包含_id欄位,即使在相應的find()方法中不包含_id欄位。

SQL查詢語句

MongoDB find()語句

SELECT *FROM users

db.users.find()

SELECT id,        user_id,        status FROM users

db.users.find(    { },    { user_id: 1, status: 1 })

SELECT user_id, statusFROM users

db.users.find(    { },    { user_id: 1, status: 1, _id: 0 })

SELECT *FROM usersWHERE status = "A"

db.users.find(    { status: "A" })

SELECT user_id, statusFROM usersWHERE status = "A"

db.users.find(    { status: "A" },    { user_id: 1, status: 1, _id: 0 })

SELECT *FROM usersWHERE status != "A"

db.users.find(    { status: { $ne: "A" } })

SELECT *FROM usersWHERE status = "A"AND age = 50

db.users.find(    { status: "A",      age: 50 })

SELECT *FROM usersWHERE status = "A"OR age = 50

db.users.find(    { $or: [ { status: "A" } ,             { age: 50 } ] })

SELECT *FROM usersWHERE age > 25

db.users.find(    { age: { $gt: 25 } })

SELECT *FROM usersWHERE age < 25

db.users.find(   { age: { $lt: 25 } })

SELECT *FROM usersWHERE age > 25AND   age <= 50

db.users.find(   { age: { $gt: 25, $lte: 50 } })

SELECT *FROM usersWHERE user_id like "%bc%"

db.users.find( { user_id: /bc/ } )

SELECT *FROM usersWHERE user_id like "bc%"

db.users.find( { user_id: /^bc/ } )

SELECT *FROM usersWHERE status = "A"ORDER BY user_id ASC

db.users.find( { status: "A" } ).sort( { user_id: 1 } )

SELECT *FROM usersWHERE status = "A"ORDER BY user_id DESC

db.users.find( { status: "A" } ).sort( { user_id: -1 } )

SELECT COUNT(*)FROM users

db.users.count() 或 db.users.find().count()

SELECT COUNT(user_id)FROM users

db.users.count( { user_id: { $exists: true } } ) 或 db.users.find( { user_id: { $exists: true } } ).count()

SELECT COUNT(*)FROM usersWHERE age > 30

db.users.count( { age: { $gt: 30 } } ) 或db.users.find( { age: { $gt: 30 } } ).count()

SELECT DISTINCT(status)FROM users

db.users.distinct( "status" )

SELECT *FROM usersLIMIT 1

db.users.findOne() 或 db.users.find().limit(1)

SELECT *FROM usersLIMIT 5SKIP 10

db.users.find().limit(5).skip(10)

EXPLAIN SELECT *FROM usersWHERE status = "A"

db.users.find( { status: "A" } ).explain()

更新記錄

下表展示了更新操作的對應關係

SQL更新語句

MongoDB update()語句

UPDATE usersSET status = "C"WHERE age > 25

db.users.update(    { age: { $gt: 25 } },   { $set: { status: "C" } },   { multi: true } )

UPDATE usersSET age = age + 3WHERE status = "A"

db.users.update(    { status: "A" } ,   { $inc: { age: 3 } },   { multi: true } )

刪除記錄

下表展示了更刪除操作的對應關係

SQL更新語句

MongoDB update()語句

DELETE FROM usersWHERE status = "D"

db.users.remove( { status: "D" } )

DELETE FROM users

db.users.remove({})

5 讀關注

3.2版本新增

MongoDB3.2為副本集和副本集分片引入了readConcern 查詢選項。預設地,執在行查詢操作時,MongoDB使用“local”讀關注來返回可用的MongoDB例項上的最新資料。即使資料沒有被儲存在副本集主成員中並且可能已經回滾。

儲存引擎和驅動支援

對於WiredTiger 儲存引擎,readConcern選項允許客戶端選擇讀隔離級別。你可以指定“majority”讀關注來讀取已經寫入副本集主成員的資料並且資料不能回滾。

對於MMAPv1儲存引擎,只能將readConcern 指定為“local”。

提示:

serverStatus 命令返回欄位storageEngine.supportsCommittedReads指明儲存引擎是否支援“majority”讀關注。

讀關注級別

預設地,MongoDB readConcern被配置為“local”,這不保證讀到的資料是不被回滾。

如果指定readConcern 為"majority" 讀取已經寫入副本集主成員的資料,這樣的資料不會回滾。

級別

描述

"local"

預設級別。查詢返回MongoDB例項中的最新的資料。不保證資料被寫入副本集主成員。

"majority"

查詢操作返回MongoDB例項中寫入副本集主成員的最新資料拷貝。 為了使用 "majority"級的讀關注,必須使用WiredTiger 儲存引擎並且使用enableMajorityReadConcern命令列選項(或者使用replication.enableMajorityReadConcern來設定配置檔案)。 只有使用副本集選舉協議版本1(protocol version 1)的副本集才支援“majority”,副本集使用版本0(protocol version 0)則不支援“majority”。 為了讓一個執行緒讀取它自己寫入的資料,在副本集主成員上使用 "majority"級讀關注和“majority”級寫關注。

除了讀關注級別,一個節點上的最新資料可能不是系統中的最新資料。

readConcern 選項

使用readConcern選項來指定讀關注級別:

readConcern: { level: <"majority"|"local"> }

對於level欄位,指定值為"majority" 或 "local"。

readConcern 選項在下列操作中也可用:

mongo shell中的db.collection.find()方法指定讀關注,使用cursor.readConcern()方法。

6 寫關注

寫關注描述了來自於MongoDB的對獨立的mongod 或者副本集或者分片叢集執行寫操作的確認級別。對於一個分片叢集,mongos例項會將寫關注傳遞給每一片。

3.2版本中的變化是:對於使用protocolVersion: 1 並啟用journal的副本集 。

  • w: "majority"表明 j: true
  • 即使 j 選項被設定為向主成員寫,當資料已經寫入第二成員(Secondary members)各自的磁碟後,第二成員仍會確認複製寫操作。

2.6版本的變化:新的協議完善了寫操作的寫關注並消除了呼叫getLastError 的需求。之前的版本為了指定寫關注需要在寫操作後立即呼叫getLastError

寫關注規範

寫關注文件包括下列欄位:

{ w: <value>, j: <boolean>, wtimeout: <number> }

  • w選項請求確認寫操作已經傳播到了指定序號的mongod例項上或指定標記的mongod 例項上。
  • j 選項請求確認寫操作已經寫入日誌。
  • wtimeout 指定了時間限制,防止寫操作無限期的阻塞程序。

w 選項

w選項請求確認寫操作已經傳播到了指定序號的mongod例項上或指定標記的mongod 例項上。

使用w選項,w: <value>是可用的。

注:

除非j:true,否則在記憶體中應用寫操作以後,獨立的mongod例項和副本集主成員會設定寫操作確認。

3.2:版本中的變化:對於使用protocolVersion: 1的副本集,不管j 選項如何配置,資料寫入第二成員(Secondary members)各自的磁碟後,第二成員確認複製寫操作。

描述

<number>

請求確認寫操作已經傳播到了指定序號的mongod例項。例如: w: 1 請求確認寫操作已經傳播到了獨立的mongod 或者副本集主成員。 w: 1是MongoDB預設的。 w: 0 不對寫操作請求確認,然而,設定為w: 0 ,返回資訊或許會包括應用程式中的socket 異常和網路錯誤。 如果指定w: 0 但是 j: true,那麼j: true確保了來自獨立的mongod 或者副本集主成員的確認請求。 將number設定為大於1僅對來自副本集指定成員(包括主成員)的確認請求有效。

"majority"

3.2版本中新增 寫操作確認請求傳播到選中節點的大多數上,包括主成員,並且已被寫入各自的磁碟日誌。 對於副本集使用了 protocolVersion: 1, w: "majority" 表明j: true。因此不像w: <number>,使用w: "majority"主副本集也會在寫確認之前寫磁碟日誌。 將寫確認設定為w:"majority"的寫操作返回客戶端後,客戶端會以讀關注設定為"majority" 的方式讀取結果。

<tag set>

寫操作確認請求傳播到了指定標籤的副本整合員。

J選項請求確認寫操作被記錄到了日誌。

j

請求確認mongod例項將寫操作記錄到了日誌,其中指定w: <value>。僅靠j: true不能保證寫操作不會回滾,由於副本集主成員故障轉移。 3.2版本中的變化:設定j: true,MongoDB僅當請求成員將寫操作記錄到了日誌後返回結果。在一個複製集內的寫關注,之前的版本中j: true,請求副本集主成員寫日誌,而不管w: <value>如何設定。 如果日誌可用的話,對於使用protocolVersion: 1的副本集,w: "majority" 表明 j: true。預設地寫日誌是可用的。

2.6版本中的變化,對於mongod 或者執行--nojournal選項的mongos ,指定j: true的寫關注會產生錯誤 。之前的版本忽略j: true。

wtimeout

對於寫關注,選項指定了以毫秒為單位的時間限制,wtimeout 是唯一的可將w值設定為大於1的。

如果超過指定的時間限制,wtimeout 會引起寫操作返回包含錯誤,即使請求的寫關注最終會成功。當寫操作返回時,在寫關注超過wtimeout時間限制以前,MongoDB 不會取消對成功資料的修改。

如果你沒有為寫關注指定wtimeout 選項,指定級別的寫關注不可實現,寫操作將會無限期阻塞。指定wtimeout 為0等價於無wtimeout 選項的寫關注。

-----------------------------------------------------------------------------------------

時間倉促,水平有限,如有不當之處,歡迎指正。