MongoDB—CRUD

mongodb Collection

命名規範

  • 集合名第一個字符必須是字母
  • 集合名不可以超過128個字符
  • 集合名不可以包含 $ 符號,因爲 $ 是 mongodb 中的系統保留字符
  • 集合名不可以包含 空格
  • 集合名不能以"system."開頭,這是爲系統集合保留的前綴

創建集合

直接插入文檔

  • mongodb 會自動創建集合

db.createCollection

https://docs.mongodb.com/v4.2/reference/method/db.createCollection/

  • 創建一個新集合
  • 一般用來創建具有特定選項的集合
格式
db.createCollection( <name>,
   {
     capped: <boolean>,
     autoIndexId: <boolean>,
     size: <number>,
     max: <number>,
     storageEngine: <document>,
     validator: <document>,
     validationLevel: <string>,
     validationAction: <string>,
     indexOptionDefaults: <document>,
     viewOn: <string>,              // Added in MongoDB 3.4
     pipeline: <pipeline>,          // Added in MongoDB 3.4
     collation: <document>,         // Added in MongoDB 3.4
     writeConcern: <document>
   }
)
  • name

    • 類型:字符串
    • 描述:要創建的集合名稱
  • options

    • 類型:document

    • 描述:集合的相關配置

      • capped

        • 類型:布爾
        • 描述:
          • true:創建一個固定大小的集合,必須結合 size 選項使用
      • autoIndexId

        3.2版本之後棄用

        從4.0版本開始,不能在 local 以外的數據庫中設置此選項

        官方不推薦使用!!!

        • 類型:布爾
        • 描述:
          • false:不會自動將_id 字段創建爲索引
      • size

        • 類型:number
        • 描述:
          • 指定固定集合的大小(字節),必須結合 capped 使用
          • 當固定集合超過設定的大小時,mongodb會刪除舊文檔爲新文檔騰出空間
      • max

        • 類型:number
        • 描述:
          • 指定固定集合中可存放的最大文檔數量
          • 當固定集合中的文檔數量超過設定的數量,mongodb會自動刪除舊文檔
          • size 選項的優先級高於 max 選項,如果一個固定集合在達到最大文檔數量之前達到的佔用空間大小的限制,則mongodb依然會刪除舊文檔
          • 要使用此選項應確保 size 選項足以包含文檔的最大數量
      • storageEngine

        • 類型:document

        • 描述:

          • 設定集合使用的存儲引擎配置(僅對於 WiredTiger 存儲引擎)

          • 格式

            { <storage-engine-name>: <options> }
            
      • validator

        • 類型:document
        • 描述:
          • 允許用戶在創建集合時添加數據校驗功能
      • validationLevel

        • 類型:字符串

        • 描述:確定MongoDB在更新過程中對現有文檔應用驗證規則的嚴格程度

          • "off"

            關閉校驗規則

          • "strict" 【默認】

            對文檔所有的更新和新增操作進行驗證

          • "moderate"

            ['mɒdəreɪt] 適度的

            僅對 已符合校驗規則的 現有文檔 進行新增和更改驗證,對 不符合校驗規則的 現有文檔不再進行操作校驗

      • validationAction

        • 類型:字符串

        • 描述:對於數據校驗無效的文檔的處理措施,僅適用於 validationLevel 確定的那些文檔

          • "error"【默認】

            如果新增或更新操作不符合校驗規則,則mongodb自動報錯

            在發生寫操作之前,文檔必須通過校驗,否則寫操作失敗

          • "warn"

            如果新增或更新操作不符合校驗規則,mongodb不會報錯,但會把錯誤信息記錄在日誌中

      • indexOptionDefaults

        • 類型:document
        • 描述:設定索引使用的存儲引擎配置
      • viewOn

        • 類型:字符串
        • 描述:指定用來創建視圖的原集合或原視圖名稱
      • pipeline

        • 類型:數組
        • 描述:包含聚合管道階段的數組
      • collation

        • 類型:document
        • 描述:指定集合的默認排序規則
      • writeConcern

        • 類型:document
        • 描述:指定集合的寫入策略,如果忽略則使用默認寫入策略

權限控制

具有 readWrite 內建角色的用戶具有上述操作的所有權限,可將角色授予現有用戶用來執行上述操作

示例
  • 創建固定集合

    db.createCollection("log", { capped : true, size : 5242880, max : 5000 } )
    
  • 創建具有數據校驗的集合

    db.createCollection( "contacts", {
       validator: { $jsonSchema: {
          bsonType: "object",
          required: [ "phone" ],
          properties: {
             phone: {
                bsonType: "string",
                description: "must be a string and is required"
             },
             email: {
                bsonType : "string",
                pattern : "@mongodb\.com$",
                description: "must be a string and match the regular expression pattern"
             },
             status: {
                enum: [ "Unknown", "Incomplete" ],
                description: "can only be one of the enum values"
             }
          }
       } }
    } )
    

    插入

    db.contacts.insert( { name: "Amanda", status: "Updated" } )
    

    報錯

    WriteResult({
       "nInserted" : 0,
       "writeError" : {
          "code" : 121,
          "errmsg" : "Document failed validation"
       }
    })
    

刪除集合

db.collection.drop

  • 刪除集合或視圖,同時刪除跟集合關聯的索引

格式

db.collection.drop( { writeConcern: <document> } )

Returns

  • true

    刪除成功

  • false

    集合不存在

查詢集合

查詢當前數據庫中有哪些集合

show collections

show tables

重命名

db.collection.renameCollection

  • 重命名集合
  • 不支持分片集合和視圖

格式

db.collection.renameCollection(target, dropTarget)
  • target

    • 類型:字符串
    • 描述:新名稱
  • dropTarget

    • 類型:布爾

    • 描述:

      • true

        如果新名稱已經存在,則在重命名之前,刪除已經存在的新名稱集合

      • false【默認】

        如果新名稱已經存在,則重命名失敗

        "errmsg" : "target namespace exists"

示例

db.rrecord.renameCollection("record")
  • 將 rrecord 重命名爲 record
  • 如果 record 集合已經存在,則操作失敗

固定集合

capped collection

具有 固定大小的 存儲空間的 集合

特點

  • 基於文檔的插入順序存儲於磁盤中

  • 基於插入順序的 插入和查詢操作 具有很高性能

    寫入速度非常塊

    查詢具有順序的文檔時,查詢速度很快

  • 工作機制類似循環緩存區,一旦集合填滿了所分配的空間,就會自動刪除最舊的文檔,用來插入新文檔

  • 固定集合可以確保文檔的插入順序,因此不需要爲插入順序建立索引,可以支持非常高的插入吞吐量

    在不指定順序的查詢操作中,mongodb 保證查詢結果的順序與插入順序一致

  • 默認情況下,固定集合有一個_id字段和建立在其之上的索引

  • 存儲空間的大小爲 256 的整數倍,最小空間爲 4096 字節

限制

  • 與TTL索引不兼容

    TTL 是固定集合的替代方案

  • 不能更改文檔大小

  • 不能使用 delete 指令刪除固定集合中的文檔,只能使用 drop 指令刪除集合再重新創建

  • 固定集合不能分片

  • 聚合管道階段中的 $out 結果不能寫入固定集合

  • 從MongoDB 4.2開始,事務中的固定集合不支持寫數據,但支持讀取數據

創建

db.createCollection
  • 創建新的固定集合

格式

db.createCollection( <name>, { capped:true, size: <number1>, max: <number2> } )
  • capped:true
  • size: <number1> 指定固定集合空間大小
  • max:<number2> 指定固定集合中文檔數量
db.runCommand
  • 把當前集合轉換爲固定集合
  • 執行過程中持有一個數據庫獨佔鎖,其他鎖定同一數據庫的操作將被阻塞,直到操作完成

格式

db.runCommand( "convertToCapped": <name>,  size: <number1> )
  • name 當前集合名
  • size: <number1> 指定固定集合空間大小

檢驗

db.collection.isCapped
db.collection.isCapped()

返回結果

  • true:是固定集合
  • false,非固定集合

應用

  • 存儲由大容量系統生成的日誌信息,在沒有索引的情況下,使用固定集合插入文檔的速度接近於將日誌信息直接寫入文件系統的速度

    例如mongodb中的用來同步複製的 oplog 就是一個固定集合

  • 緩存少量的數據

mongodb CRUD

create read update delete

Create

  • collection 需要指定具體的集合名,如果集合不存在,則會創建

db.collection.insert

  • 插入文檔

格式

db.collection.insert(
   <document or array of documents>,
   {
     writeConcern: <document>,
     ordered: <boolean>
   }
)
  • document or array of documents

    • 插入一個或多個文檔
    • 插入一個文檔,文檔內容放在{ } 中,如 { doc }
    • 插入多個文檔,單個文檔內容放在{ }中,然後一起放在[ ] 中,如[ { doc1 }, { doc2 } ]
  • writeConcern

  • 【可選】是否使用寫入策略

  • ordered

    • 【可選】默認爲true
    • 若爲 true,表示有序插入,當有一個文檔插入時發生錯誤,則後續文檔不再繼續插入
    • 若爲 false,表示無序插入,當有一個文檔插入時發生錯誤,會繼續執行後續文檔的插入動作

insert 包含 insertOne 和 insertMany

示例

> db.person.insert([
... {
...  name:"lfp",
...  age:18,
...  birth: new Date("1992-10-24")
... },
... {
...  name:"xm",
...  age:19,
...  birth: new Date("1991-01-22")
... }
... ])

db.collection.insertOne

  • 插入一個文檔

格式

db.collection.insertOne(
   <document>,
   {
      writeConcern: <document>
   }
)

db.collection.insertMany

  • 插入多個文檔

格式

db.collection.insertMany(
   [ <document 1> , <document 2>, ... ],
   {
      writeConcern: <document>,
      ordered: <boolean>
   }
)

db.collection.save

  • 插入一個新的文檔
  • 更新一個已經存在的文檔(需通過_id 字段進行覆蓋式更新)
  • 插入主鍵相同的文檔時,insert 方法會報錯,save 方法會覆蓋原文檔

格式

db.collection.save(
   <document>,
   {
     writeConcern: <document>
   }
)

新版本中有可能被廢棄,建議使用 insertOne 或 replaceOne

4.2 版本測試仍可以使用

  • document 需要保存的文檔
  • writeConcern
  • 【可選】是否使用寫入策略

示例

當插入_id 主鍵相同的文檔時會覆蓋

> db.person.save({
...  _id:ObjectId("5f2d16c2cbb6771db2cf3db9"),
...   name:"lfp",
...   age:23,
...   birth:new Date("1992-10-24")
... })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

  • 5f2d16c2cbb6771db2cf3db9 該id已經存在
  • 覆蓋原文檔(刪除原文檔,使用新插入的文檔)

Read/Query

query an array

  • 查詢數組元素中是否包含指定的元素,針對的是數組中的每一個元素

    { <array field>: { <operator1>: <value1>, ... } }
    

    例如

    db.inventory.find( { dim_cm: { $gt: 25 } } )
    
    • 數組中的元素值大於25

db.collection.find

  • 查詢集合或視圖中的文檔並返回
格式
db.collection.find(
   <query>,
   <projection>
)
  • query【可選】

  • 類型:document

  • 描述

    • 查詢條件
    • 通過查詢操作符指定
    • 忽略該選項或指定爲空文檔{ },將返回集合中所有的文檔
  • projection【可選】

    • 類型:document => { field1: <value>, field2: <value> ... }

      • 字段值爲1,表示顯示此字段(include)

      • 字段值爲0,表示不顯示此字段(exclude)

        _id字段默認顯示,若不想顯示則指定 {"_id":0}

      • 不能同時包含 include 和 exclude 行爲,除了_id 字段

      • 通過 Projection 操作符指定

        在視圖中查詢時,不能使用 $、$eleMatch、$slice、$meta 操作符

    • 描述

      • 指定查詢結果中需要顯示的字段
      • 如果忽略則顯示文檔中的所有字段
Returns

返回指向文檔的遊標

遊標 cursor 指向符合查詢條件的文檔,find 方法實際返回的是指向文檔的遊標

示例

文檔

The bios Example Collection

  • 返回集合中的所有文檔

    db.bios.find()
    
  • 返回符合指定條件的文檔

    • 相等操作符$eq
    db.bios.find( { _id : 5 } )
    
    db.bios.find( { "name.last" :  "Hopper" } )
    
    • 其他操作符
    db.bios.find(
    { birth : { $gt : new Date('1992-01-01')  } }
    )
    
    // 正則
    db.bios.find(
    { "name.last" : { $regex : /^N/ } }
    )
    
    // 範圍,一個子文檔中用多個查詢操作符表示範圍
    db.bios.find(
    { birth : { $gt: new Date('1940-01-01'), $lt: new Date('1960-01-01') } }
    )
    
    // 多條件查詢
    db.bios.find(
        {
        birth : { $gt :  new Date('1940-01-01')  },
        death : { $exist : false }
        }
    )
    
    • 除了 $eq 可以省略,其他比較操作符都是一個子文檔類型

db.collection.findOne

  • 查詢集合或視圖中的文檔,並返回符合條件的第一個文檔

    按照自然順序,即磁盤上文檔的順序,在 capped 集合中,相當於插入順序

  • 如果沒有符合條件的文檔,則返回 null

格式

db.collection.find(
   <query>,
   <projection>
)
  • query 和 projection 同 find

Returns

返回文檔而非遊標

示例

db.bios.findOne(
   {
     $or: [
            { 'name.first' : /^G/ },
            { birth: { $lt: new Date('01/01/1945') } }
          ]
   }
)
  • 查詢條件是
    1. 嵌套文檔name中的first字段以 G 開頭 或
    2. birth 字段 小於 new Date('01/01/1945')

db.collection.findAndModify

db.collection.findOneAndDelete

db.collection.findOneAndReplace

db.collection.findOneAndUpdate

Update

  • collection 需要指定具體的集合名

db.collection.update

  • 更新文檔
格式
db.collection.update(
   <query>,
   <update>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ],
     hint:  <document|string>        // Available starting in MongoDB 4.2
   }
)
  • query

    • 類型:document

    • 描述:

      • 更新條件,符合更新條件的文檔將被更新

      • 使用與find()方法中相同的查詢選擇器

  • update

    • 類型:document 或 pipeline

      • document

        • 如果是更新文檔,則文檔內容是 操作表達式
        • 如果是替換文檔,則文檔內容是 文檔鍵值對
      • pipeline

        4.2版本新增

        聚合管道

    • 描述:更新操作

  • options

    • upsert

      • 類型:布爾【可選】

        • true

          若沒有匹配的文檔,會插入當前文檔

        • false 【默認】

          若沒有匹配的文檔,則不插入當前文檔

      • 描述:

    • multi

      • 類型:布爾【可選】

      • true

        更新所有匹配的文檔

      • false【默認】

        只更新匹配到的第一個文檔

    • writeConcern

      • 類型:文檔 ?
        • { w:1 } 【默認】
      • 描述:寫入策略
    • collation

      • 類型:文檔【可選】
      • 爲字符串指定特定於語言的排序規則
    • arrayFilters

      • 類型:數組【可選,3.6新增】

        • 一個標識符只能對應一個數組過濾器文檔

          // INVALID
          
          [
            { "x.a": { $gt: 85 } },
            { "x.b": { $gt: 80 } }
          ]
          
          // Example 1
          [
            { $or: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
          ]
          // Example 2
          [
            { $and: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
          ]
          // Example 3
          [
            { "x.a": { $gt: 85 }, "x.b": { $gt: 80 } }
          ]
          
        • 當 更新文檔 是對嵌套數組中的元素進行更改,則會出現兩個標識符,此時會有兩個數組過濾器文檔

      • 描述

        • 數組元素的過濾條件,用來確定哪些元素被更新(數組過濾器)

        • 當 update 類型是 document 時,使用 $[ < identifier > ] 來定義一個 標識符,代表元素下標,在 arrayFilters 中用 identifier 代表元素,設定元素的過濾條件

          $[ < identifier > ] 整體代表元素下標
          都需要用引號包裹 '$' 'identifier'

        • 當 update 類型是 聚合管道時,不能使用 arrayFilters 選項

Returns

返回一個 WriteResult 文檔,包含操作的狀態

  • Successful Results

    執行成功

    • nMatched

      符合條件的文檔數量

    • nUpserted

      更新操作插入的文檔數量

    • nModified

      更新文檔的數量

    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    
  • Write Concern Errors

    執行時發生寫入策略錯誤,需要用 try-catch 捕獲

    • writeConcernError

      寫入策略錯誤對象

    WriteResult({
       "nMatched" : 1,
       "nUpserted" : 0,
       "nModified" : 1,
       "writeConcernError" : {
          "code" : 64,
          "errmsg" : "waiting for replication timed out at shard-a"
       }
    })
    
  • Errors Unrelated to Write Concern

    執行時發生其他錯誤(非寫入策略錯誤),需要用 try-catch 捕獲

    • write Error

      錯誤對象

    WriteResult({
       "nMatched" : 0,
       "nUpserted" : 0,
       "nModified" : 0,
       "writeError" : {
          "code" : 7,
          "errmsg" : "could not contact primary for replica set shard-a"
       }
    })
    
示例
  • 數組過濾器

    db.students.insertMany([
       { "_id" : 1, "grades" : [ 95, 92, 90 ] },
       { "_id" : 2, "grades" : [ 98, 100, 102 ] },
       { "_id" : 3, "grades" : [ 95, 110, 100 ] }
    ])
    

    更新

    db.students.update(
       { grades: { $gte: 100 } },
       { $set: { "grades.$[element]" : 100 } },
       {
         multi: true,
         arrayFilters: [ { "element": { $gte: 100 } } ]
       }
    )
    
    • 更新 grades 數組中某個元素值大於等於100的 文檔
    • 如果文檔中的grades數組中的元素值大於等於100,則將其更改爲100

db.collection.updateOne

  • 只更新一個符合條件的文檔

格式

db.collection.updateOne(
   <filter>,
   <update>,
   {
     upsert: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ],
     hint:  <document|string>        // Available starting in MongoDB 4.2.1
   }
)
  • filter

    • 類型:document

    • 描述:

      • 選擇條件,符合條件的文檔將被更新

      • 使用與find()方法中相同的查詢選擇器

      • 如果指定一個空文檔{ },將更新集合中的第一個文檔

  • writeConcern

    • 類型:document
      • 如果忽略則使用默認策略
    • 描述:寫入策略

Returns

同 update 方法

示例

  • filter 爲空文檔

    文檔

    db.members.insertMany([
        { "_id" : 1, "name" : "Central Perk Cafe", "Borough" : "Manhattan" },
        { "_id" : 2, "name" : "Rock A Feller Bar and Grill", "Borough" : "Queens", "violations" : 2 },
        { "_id" : 3, "name" : "Empire State Pub", "Borough" : "Brooklyn", "violations" : 0 }
    ])
    

    更新

      db.members.updateOne(
          { },
          { $set:{ "villations":4 }}
      )
    
    • 只修改集合中第一個文檔

db.collection.updateMany

  • 更新所有符合條件的的文檔

格式

db.collection.updateMany(
   <filter>,
   <update>,
   {
     upsert: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ],
     hint:  <document|string>        // Available starting in MongoDB 4.2.1
   }
)
  • filter

    • 類型:document

    • 描述:

      • 選擇條件,符合條件的文檔將被更新

      • 使用與find()方法中相同的查詢選擇器

      • 如果指定一個空文檔{ },將更新集合中的所有文檔

  • writeConcern

    • 類型:document
      • 如果忽略則使用默認策略
    • 描述:寫入策略

Returns

  • 方法將返回一個文檔,包含以下字段

    • acknowledged

      • 類型:布爾

        • true

          執行寫入策略

        • false

          寫入策略被禁用

    • matchedCount

      • 類型:number
      • 描述:符合條件的文檔數量
    • modifiedCount

      • 類型:number
      • 描述:被更新的文檔數量
    • upsertedId

      • 被更新文檔的_id

示例

  • filter 爲空,更新所有文檔

    文檔

    db.members.insertMany([
        { "_id" : 1, "name" : "Central Perk Cafe", "Borough" : "Manhattan" },
        { "_id" : 2, "name" : "Rock A Feller Bar and Grill", "Borough" : "Queens", "violations" : 2 },
        { "_id" : 3, "name" : "Empire State Pub", "Borough" : "Brooklyn", "violations" : 0 }
    ])
    

    更新

      db.members.updateMany(
          { },
          { $set:{ "age":27 }}
      )
    
    • 所有文檔都新增了 age 字段

db.collection.replaceOne

  • 替換一個符合條件的文檔

格式

db.collection.replaceOne(
   <filter>,
   <replacement>,
   {
     upsert: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     hint: <document|string>                   // Available starting in 4.2.1
   }
)
  • filter

    • 類型:document

    • 描述:

      • 選擇條件,符合條件的文檔將被替換

      • 使用與find()方法中相同的查詢選擇器

      • 如果指定一個空文檔{ },將替換集合中的第一個文檔

  • replacement

    • 類型:文檔
    • 描述:
      • 替換文檔
      • 不能包含更新操作符
  • writeConcern

    • 類型:文檔
      • 如果忽略則使用默認策略
    • 描述:寫入策略

Returns

同 updateMany

示例

  • 使用 upsert

    文檔

    db.members.insertMany([
        { "_id" : 1, "name" : "Central Perk Cafe", "Borough" : "Manhattan",  "violations" : 3 },
        { "_id" : 2, "name" : "Rock A Feller Bar and Grill", "Borough" : "Queens", "violations" : 2 },
        { "_id" : 3, "name" : "Empire State Pub", "Borough" : "Brooklyn", "violations" : 0 }
    ])
    

    更新

    try {
       db.members.replaceOne(
           { "name" : "Pizza Rat's Pizzaria" },
           { "_id": 4, "name" : "Pizza Rat's Pizzaria", "Borough" : "Manhattan", "violations" : 8 },
           { upsert: true }
       );
    } catch (e){
       print(e);
    }
    
    • 因爲使用了 upsert : true 選項,沒有符合條件的文檔時,則插入替換文檔

Delete

db.collection.remove

  • 刪除符合條件的文檔
格式
db.collection.remove(
   <query>,
   <justOne>
)
  • query

    • 類型:document
    • 描述
      • 刪除條件
      • 通過查詢操作符指定
      • 如果指定一個空文檔{ },將刪除集合中的所有文檔
  • justOne【可選】

    • 類型:布爾

      • true

        僅刪除符合條件的第一個文檔

      • false【默認】

        刪除符合條件的所有文檔

    • 描述:是否僅刪除第一個符合條件的文檔

db.collection.remove(
   <query>,
   {
     justOne: <boolean>,
     writeConcern: <document>,
     collation: <document>
   }
)
  • query

    同上

  • justOne

    同上

  • writeConcern

    • 類型:document
      • 如果忽略則使用默認寫入策略
    • 描述:寫入策略
Returns

返回一個 WriteResult 包含操作狀態

  • Successful Results

    執行成功

    • nRemoved

      刪除文檔的數量

    WriteResult({ "nRemoved" : 4 })
    
  • Write Concern Errors

    執行時發生寫入策略錯誤,需要用 try-catch 捕獲

    • writeConcernError

      寫入策略錯誤對象

  • Errors Unrelated to Write Concern

    執行時發生其他錯誤(非寫入策略錯誤),需要用 try-catch 捕獲

    • write Error

      錯誤對象

示例
  • 格式1,使用 justOne 選項

    文檔

    db.myColl.insert([
        { _id: 1, category: "café", status: "A" },
        { _id: 2, category: "cafe", status: "a" },
        { _id: 3, category: "cafE", status: "a" },
    ])
    

    刪除

    db.myColl.remove(
        {status:"a"},
        true
    )
    
    • 指定 justOne 爲 true,只刪除_id 爲2 的文檔
  • 格式2,使用 justOne 選項

    刪除

    db.myColl.remove(
        {status:"a"},
        {justOne:true}
    )
    
    • 使用 justOne 選項,只刪除_id 爲2 的文檔
  • 刪除集合中所有文檔

    刪除

    db.myColl.remove(
        {}
    )
    

db.collection.deleteOne

  • 刪除一個符合條件的文檔

格式

db.collection.deleteOne(
   <filter>,
   {
      writeConcern: <document>,
      collation: <document>
   }
)
  • filter
    • 類型:document
    • 描述:
      • 刪除條件
      • 通過操作符指定
      • 如果指定一個空文檔{ },將刪除集合中的第一個文檔

Returns

返回一個文檔,包含

  • acknowledged

    • 類型:布爾

      • true

        執行寫入策略

      • false

        寫入策略被禁用

  • deletedCount

    • 類型:number
    • 描述:刪除文檔的數量

db.collection.deleteMany

  • 刪除所有符合條件的文檔

格式

db.collection.deleteMany(
   <filter>,
   {
      writeConcern: <document>,
      collation: <document>
   }
)
  • filter
    • 類型:document
    • 描述
      • 刪除條件
      • 通過查詢操作符指定
      • 如果指定一個空文檔{ },將刪除集合中的所有文檔

Returns

同 deleteOne

db.collection.find().pretty()

  • 打印集合中的所有文檔,並以更易讀的方式顯示

Operators

Query and Projection Operators

  • 不包含字段 符合條件的操作符

    $ne、$nin、$nor、$not

Comparison Operators

  • 對大多數數據類型,僅當字段值類型和指定值類型相同時進行比較

    不同時指定比較規則?

  • 操作符表達式文檔 本身 作爲 字段/操作符 的值

$eq
  • 指定相等條件,表示字段的值等於指定的值
  • 如果字段爲數組類型,則表示字段數組包含指定值的元素
  • 如果指定的 value 是數組,則匹配的文檔中,指定字段正好匹配數組 或 指定字段包含一個恰好匹配數組的元素(數組元素的順序也要匹配)

格式

{ field: { $eq: value } }
// 等價於下面的寫法
{ field: <value> }
  • 可以省略 $eq ,即默認 field : value 形式就是相等條件

示例

db.inventory.find( { tags: { $eq: [ "A", "B" ] } } )
db.inventory.find( { tags: [ "A", "B" ] } )

db.inventory.find( { "item.name": { $eq: "ab" } } )
db.inventory.find( { "item.name": "ab" } )
$gt
  • 指定大於條件,表示字段的值大於>指定的值(greater than)

格式

{field: {$gt: value} }
  • 不可以省略,操作符表達式 作爲一個子文檔格式

示例

db.inventory.update( { "carrier.fee": { $gt: 2 } }, { $set: { price: 9.99 } } )
  • 嵌套文檔的 fee 字段的值大於2的 第一個文檔將被添加一個 price 字段,值爲 9.99
$gte
  • 指定大於等於條件,表示字段的值大於等於>=指定的值(greater then or equal)

格式

{field: {$gte: value} }
$in
  • 表示字段的值 等於 指定數組中任意一個元素

  • 如果字段的值是數組類型,則表示字段數組 至少 包含 指定數組中任意一個元素

  • 對同一個字段執行相等性檢查時,優於 $or 邏輯操作符

  • 可以通過正則對象表達式 /pattern/ 指定匹配的值

    在 $in 表達式中不能使用 $regex 操作符表達式

格式

{ field: { $in: [<value1>, <value2>, ... <valueN> ] } }
  • 值爲數組類型

示例

  • 字段值是數組

    文檔

    { _id: 1, item: "abc", qty: 10, tags: [ "school", "clothing" ], sale: false }
    

    更新

    db.inventory.update(
                         { tags: { $in: ["appliances", "school"] } },
                         { $set: { sale:true } }
                       )
    
    • 更新條件是 tags 數組中至少包含 "appliances" 或 "school" 元素中的一個
  • 正則表達式

    db.inventory.find( { tags: { $in: [ /^be/, /^st/ ] } } )
    
    • 如果 tags 是字符串,則匹配以 be 或 st 開頭的字符串
    • 如果 tags 是數組,則至少有一個元素是以 be 或 st 開頭的字符串
$lt
  • 指定小於條件,表示字段的值小於<指定的值(less than)

格式

{field: {$lt: value} }
$lte
  • 指定小於等於條件,表示字段的值小於等於<=指定的值(less than or equal)

格式

{ field: { $lte: value} }
$ne
  • 指定不相等條件,表示字段的值不等於指定的值,或者文檔中 不包含該字段(not equal)

  • 該操作符選擇性不好,因爲它經常匹配索引的很大一部分。因此,很多情況下,帶有索引的 $ne 查詢的性能並不比不帶索引的 $ne 查詢性能好

    不帶索引則必須掃描集合中所有的文檔

格式

 {field: {$ne: value} }
$nin
  • 表示字段的值不等於指定數組中任何一個元素, 或者文檔中 不包含該字段(not in)

  • 如果字段的值是數組類型,則表示字段數組中不包含指定數組中任何一個元素

  • 該操作符選擇性不好,因爲它經常匹配索引的很大一部分。因此,很多情況下,帶有索引的 $nin 的查詢性能並不比不帶索引的 $nin 的查詢性能好

    不帶索引則必須掃描集合中所有的文檔

格式

{ field: { $nin: [ value1, value2 ... valueN ]}
  • 值爲數組類型

示例

db.inventory.update( { tags: { $nin: [ "appliances", "school" ] } }, { $set: { sale: false } } )
  • 更新條件是 tags 數組中不包含 數組["appliances", "school"] 中的任意一個元素,或者文檔中不包含 tags 字段

Logical Operators

$and
  • 邏輯與,連接多個查詢條件,表示文檔必須符合所有條件
  • 使用短路計算,如果第一個條件不符合則不再繼續判斷後續條件
  • 以逗號分隔的表達式列表,也具有邏輯與操作(隱式 and )

格式

{ $and: [ { <expression1> }, { <expression2> } , ... , { <expressionN> } ] }
  • 值爲數組類型,元素爲操作符表達式文檔
  • 本身不作爲字段的值

示例

  • 隱式and

    db.inventory.find( { $and: [ { price: { $ne: 1.99 } }, { price: { $exists: true } } ] } )
    

    相等於

    將price字段的表達式重組,通過逗號分隔,組成一個表達式列表,用一個子文檔表示

    db.inventory.find( { price: { $ne: 1.99, $exists: true } } )
    
    • 查詢條件是:price 字段存在且值不等於 1.99 的文檔
  • 使用相同操作符的多個表達式

    db.inventory.find( {
        $and: [
            { $or: [ { qty: { $lt : 10 } }, { qty : { $gt: 50 } } ] },
            { $or: [ { sale: true }, { price : { $lt : 5 } } ] }
        ]
    } )
    
    • 使用了多次 $or 操作符,多個表達式,不能通過同一個字段的表達式重組的方式使用隱式and
    • 查詢條件是:qty字段的值小於10或大於50 且 sale字段爲true或price字段的值小於5
$not
  • 邏輯非,只用於一個查詢條件,表示文檔必須不符合該查詢條件,或者不包含該字段
  • 只能通過影響其他操作符來影響查詢結果,不能獨立檢查字段和文檔

格式

 { field: { $not: { <operator-expression> } } }
  • 值爲
    • 操作符表達式文檔

    • 正則對象表達式

      4.0.6版本之後才支持 正則操作符表達式

  • 操作符表達式 本身 作爲字段的值

示例

  • 影響其他字段

    db.inventory.find( { price: { $not: { $gt: 1.99 } } } )
    
    • $gt 表示 price 大於 1.99 的文檔,而加上 $not 則表示 price 小於或等於1.99 或 不包含 price 字段的文檔
    • 區別於 { $lte: 1.99 },表示 price 存在 且 price小於或等於1.99的文檔
  • 正則表達式

    db.inventory.find( { item: { $not: /^p.*/ } } )
    
    • 查詢條件是:item 字段的值不以字符p開頭的文檔
  • 正則操作符表達式

    db.inventory.find( { item: { $not: { $regex: "^p.*" } } } )
    db.inventory.find( { item: { $not: { $regex: /^p.*/ } } } )
    db.inventory.find( { item: { $not: /^p.*/ } } )
    
    • 查詢條件是:item 字段的值不以字符p開頭的文檔
$nor
  • 連接多個查詢條件,表示文檔必須不符合所有條件(and 操作符的反面),或者不包含該字段

格式

{ $nor: [ { <expression1> }, { <expression2> }, ...  { <expressionN> } ] }
  • 值爲數組類型,元素爲操作符表達式文檔

  • 操作符表達式 本身不作爲字段的值

  • 一般返回結果可以包括 2^表達式個數 個組合

    每個表達式有兩種情況,不符合表達式或不包含該字段

示例

  • 一般情況

    db.inventory.find( { $nor: [ { price: 1.99 }, { sale: true } ]  } )
    

  - 查詢條件是:
    1. price存在且不等於1.99 且 sale不爲true
    2. price不存在 且 sale 存在且不爲true
    3. price存在且不等於1.99 且 sale 不存在
    4. price不存在 且 sale 不存在

- 結合 $exists 操作符使用

  ```sql
  db.inventory.find( { $nor: [ { price: 1.99 }, { price: { $exists: false } },
                               { sale: true }, { sale: { $exists: false } } ] } )
  • $exists 操作符限制了 不包含字段 的情況
  • 查詢條件是:price存在且不等於1.99 且 sale存在且不爲true
$or
  • 邏輯或,連接多個查詢條件,表示文檔只要滿足其中一個條件即可
  • 對相同字段的檢測使用 $in 操作符表達式比較好

格式

{ $or: [ { <expression1> }, { <expression2> }, ... , { <expressionN> } ] }
  • 當對 $or 操作符表達式中的子句求值時,mongodb要麼進行集合掃描,要麼進行索引掃描(所有子句都必須建立索引)

示例

db.inventory.find( { $or: [ { quantity: { $lt: 20 } }, { price: 10 } ] } )

爲了支持 $or 查詢,需要給 quantity 和 price 字段建立索引

db.inventory.createIndex( { quantity: 1 } )
db.inventory.createIndex( { price: 1 } )
  • 查詢條件是
    1. quantity 字段的值小於20
    2. price字段的值等於10

Element Operators

$exists
  • 表示某個字段是否存在
  • SQL 中的 exists 操作相當於 mongodb 中的 $in

格式

{ field: { $exists: <boolean> } }
  • 值爲布爾類型

    • true,表示存在該字段(包括字段值爲null)
    • false,表示不存在該字段

    4.2 版本之前,$type:0 跟 $exists:false 是同義詞

$type
  • 表示字段的值是某個類型(BSON type ),或字段值是數組且包含一個該類型的元素

  • BSON type 可以是對應的數字或別名

  • 當指定字段類型是數組時

    • 3.6版本之前,返回字段是數組類型,並且至少包含一個數組元素的文檔
    • 3.6版本之後,返回字段是數組類型的文檔(包括 空數組 [ ]
  • 當字段類型

  • 類型

    Type Number Alias Notes
    Double 1 “double”
    String 2 “string”
    Object 3 “object”
    Array 4 “array”
    Binary data 5 “binData”
    Undefined 6 “undefined” Deprecated.
    ObjectId 7 “objectId”
    Boolean 8 “bool”
    Date 9 “date”
    Null 10 “null”
    Regular Expression 11 “regex”
    DBPointer 12 “dbPointer” Deprecated.
    JavaScript 13 “javascript”
    Symbol 14 “symbol” Deprecated.
    JavaScript (with scope) 15 “javascriptWithScope”
    32-bit integer 16 “int”
    Timestamp 17 “timestamp”
    64-bit integer 18 “long”
    Decimal128 19 “decimal” New in version 3.4.
    Min key -1 “minKey”
    Max key 127 “maxKey”
    • $type : number 會匹配4中具體類型
      • double
      • 32-bit integer(int)
      • 64-bit integer(long)
      • decimal

格式

{ field: { $type: <BSON type> } }
  • 表示字段的值類型是指定的類型
{ field: { $type: [ <BSON type1> , <BSON type2>, ... ] } }
  • 表示字段的值類型是指定類型中的任意一個

示例

  • 單個類型

    文檔

    db.addressBook.insertMany(
       [
          { "_id" : 1, address : "2030 Martian Way", zipCode : "90698345" },
          { "_id" : 2, address: "156 Lunar Place", zipCode : 43339374 },
          { "_id" : 3, address : "2324 Pluto Place", zipCode: NumberLong(3921412) },
          { "_id" : 4, address : "55 Saturn Ring" , zipCode : NumberInt(88602117) },
          { "_id" : 5, address : "104 Venus Drive", zipCode : ["834847278", "1893289032"]}
       ]
    )
    

    查詢

    db.addressBook.find( { "zipCode" : { $type : 2 } } );
    db.addressBook.find( { "zipCode" : { $type : "string" } } );
    
    • 將返回 zipCode 類型是字符串的文檔 或 zipCode 類型是數組但包含一個字符串元素的文檔

    • 結果

      { "_id" : 1, "address" : "2030 Martian Way", "zipCode" : "90698345" }
      { "_id" : 5, "address" : "104 Venus Drive", "zipCode" : [ "834847278", "1893289032" ] }
      
  • 多個類型

    文檔

    db.grades.insertMany(
       [
          { "_id" : 1, name : "Alice King" , classAverage : 87.333333333333333 },
          { "_id" : 2, name : "Bob Jenkins", classAverage : "83.52" },
          { "_id" : 3, name : "Cathy Hart", classAverage: ["94.06", 10] },
          { "_id" : 4, name : "Drew Williams" , classAverage : NumberInt("93") }
       ]
    )
    

    查詢

    db.grades.find( { "classAverage" : { $type : [ 2 , 1 ] } } );
    db.grades.find( { "classAverage" : { $type : [ "string" , "double" ] } } );
    
    • 將返回 classAverage 類型是字符串或double類型的文檔 或 classAverage 類型是數組但包含一個字符串或double類型的元素

    • 結果

      { "_id" : 1, name : "Alice King" , classAverage : 87.333333333333333 }
      { "_id" : 2, name : "Bob Jenkins", classAverage : "83.52" }
      { "_id" : 3, name : "Cathy Hart", classAverage: ["94.06", 10] }
      

Evaluation Operators

評估操作符

$expr
  • 在查詢語言中使用聚合表達式

格式

{ $expr: { <expression> } }
  • 操作符表達式 本身不作爲值
  • expression 可以是任何有效的聚合表達式

示例

  • 搭配比較聚合表達式

    文檔

    { "_id" : 1, "category" : "food", "budget": 400, "spent": 450 }
    { "_id" : 2, "category" : "drinks", "budget": 100, "spent": 150 }
    { "_id" : 3, "category" : "clothes", "budget": 100, "spent": 50 }
    { "_id" : 4, "category" : "misc", "budget": 500, "spent": 300 }
    { "_id" : 5, "category" : "travel", "budget": 200, "spent": 650 }
    

    查詢

    db.monthlyBudget.find( { $expr: { $gt: [ "$spent" , "$budget" ] } } )
    
    • $gt 聚合表達式表示,第一個字段的值大於第二個字段的值返回true,否則返回false

    • 結果

      { "_id" : 1, "category" : "food", "budget" : 400, "spent" : 450 }
      { "_id" : 2, "category" : "drinks", "budget" : 100, "spent" : 150 }
      { "_id" : 5, "category" : "travel", "budget" : 200, "spent" : 650 }
      
$jsonSchema
$mod
  • 取摸運算,表示字段的值對 指定除數 取摸 具有 指定餘數

格式

{ field: { $mod: [ divisor, remainder ] } }
  • 值爲 兩個元素的 數組,元素個數不是2個會報錯

示例

文檔

{ "_id" : 1, "item" : "abc123", "qty" : 0 }
{ "_id" : 2, "item" : "xyz123", "qty" : 5 }
{ "_id" : 3, "item" : "ijk123", "qty" : 12 }

查詢

db.inventory.find( { qty: { $mod: [ 4, 0 ] } } )
  • 查詢條件是:qty的值對4取摸餘數爲0

  • 結果

    { "_id" : 1, "item" : "abc123", "qty" : 0 }
    { "_id" : 3, "item" : "ijk123", "qty" : 12 }
    
$text
  • 對建立文本索引的所有字段進行文本搜索
  • The $text operator, by default, does not return results sorted in terms of the results’ scores
  • 限制
    • 一個查詢操作只能指定一個 $text 表達式
    • 不能出現在 $nor 表達式中
    • 不能出現在 $elemMatch 查詢表達式 或 $elemMatch 投影表達式中
    • 要在 $or 表達式中使用 $text 查詢,則 $or 表達式中的所有子句都必須建立文本索引
    • ......
    • 視圖不支持文本查詢
    • 聚合操作中
      • 包含 $text 查詢的 $match 階段,必須是管道中的第一個階段
      • $text 查詢在 stage 中只能出現一次
      • 不能出現在 $or 或 $not 表達式中
      • 默認情況下,文本搜索不會按照匹配分數的順序返回匹配的文檔。要按降序排序,請在 $sort 階段使用 $meta 聚合表達式

格式

{
  $text:
    {
      $search: <string>,
      $language: <string>,
      $caseSensitive: <boolean>,
      $diacriticSensitive: <boolean>
    }
}
  • $search

    • 類型:字符串

    • 描述:

      • mongodb 解析並用於查詢文本索引的術語字符串

      • 文本操作符將 $search 字符串中的大多數標點符號視爲分隔符,但否定術語的連字符- 和 指定短語的轉義雙引號\" \"除外

      • 轉義雙引號

        • 匹配短語,需將短語括在轉義雙引號\"

          "\"ssl certificate\""
          
        • 如果 $search 字符串包含一個短語和單個術語,則文本查詢只匹配包含短語的文檔

          "\"ssl certificate\" authority key"
          

          $text 操作符將只匹配 "ssl certificate"短語,忽略後面的單個術語 authority key

      • 連字符

        • 用於否定一個單詞,將包含否定詞的文檔從結果集中排除(連字符前面要有空格)
        • 當傳遞一個只包含否定詞的搜索字符串時,文本搜索將不匹配任何文檔
        • 用連字符連接的詞,例如 pre-market,不是否定詞。$text 操作符將連字符視爲分隔符(分別匹配兩個術語),如果想表達否定含義,則在連接詞的連字符前加一個空格,例如 pre -market
  • $language

    • 類型:字符串
    • 描述:指定搜索的停止詞列表以及詞幹分析器和記號賦予器規則的語言。如果未指定,則搜索使用索引的默認語言
  • $caseSensitive

    • 類型:布爾

    • 描述:查詢文本是否區分大小寫

      • false【默認】

        不區分

  • $diacriticSensitive

    • 類型:布爾

    • 描述:查詢文本是否區別變音符

      • false【默認】

        不區分

示例

文檔

db.articles.createIndex( { subject: "text" } )
db.articles.insert(
   [
     { _id: 1, subject: "coffee", author: "xyz", views: 50 },
     { _id: 2, subject: "Coffee Shopping", author: "efg", views: 5 },
     { _id: 3, subject: "Baking a cake", author: "abc", views: 90  },
     { _id: 4, subject: "baking", author: "xyz", views: 100 },
     { _id: 5, subject: "Café Con Leche", author: "abc", views: 200 },
     { _id: 6, subject: "Сырники", author: "jkl", views: 80 },
     { _id: 7, subject: "coffee and cream", author: "efg", views: 10 },
     { _id: 8, subject: "Cafe con Leche", author: "xyz", views: 10 }
   ]
)
  • 查詢單個術語

    db.articles.find( { $text: { $search: "coffee" } } )
    
    • 返回 subject 字段包含 "coffee" 的文檔
  • 查詢用空格分隔的字符串

    $text操作符對每個術語執行邏輯或搜索,並返回包含任何術語的文檔。

    db.articles.find( { $text: { $search: "bake coffee cake" } } )
    
    • 返回 subject 字段包含 "bake" 或 "coffee" 或 "cake" 的文檔

      { "_id" : 2, "subject" : "Coffee Shopping", "author" : "efg", "views" : 5 }
      { "_id" : 7, "subject" : "coffee and cream", "author" : "efg", "views" : 10 }
      { "_id" : 1, "subject" : "coffee", "author" : "xyz", "views" : 50 }
      { "_id" : 3, "subject" : "Baking a cake", "author" : "abc", "views" : 90 }
      { "_id" : 4, "subject" : "baking", "author" : "xyz", "views" : 100 }
      
      • 注意 baking 也被匹配爲 bake
  • 查詢短語

    db.articles.find( { $text: { $search: "\"coffee shop\"" } } )
    

    返回 subject 字段包含 "coffee shop" 的文檔

    { "_id" : 2, "subject" : "Coffee Shopping", "author" : "efg", "views" : 5 }
    
  • 否定單詞

    db.articles.find( { $text: { $search: "coffee -shop" } } )
    
    • 返回 subject 字段包含 coffee,但不包含 shop 的文檔

      { "_id" : 7, "subject" : "coffee and cream", "author" : "efg", "views" : 10 }
      { "_id" : 1, "subject" : "coffee", "author" : "xyz", "views" : 50 }
      
  • 文檔匹配分數

    db.articles.find(
       { $text: { $search: "cake" } },
       { score: { $meta: "textScore" } }
    )
    

    返回

    { "_id" : 3, "subject" : "Baking a cake", "author" : "abc", "views" : 90, "score" : 0.75 }
    
    • 返回的文檔包含一個附加的 score 字段,該字段包含文檔的匹配分數
$regex
  • 在查詢語言中使用正則表達式

    mongodb 使用 PCRE 正則表達式

格式

正則操作符表達式

{ <field>: { $regex: /pattern/, $options: '<options>' } }
{ <field>: { $regex: 'pattern', $options: '<options>' } }
{ <field>: { $regex: /pattern/<options> } }

正則對象表達式

{ <field>: /pattern/<options> }
  • 定界符可以使用 正斜槓 或 單引號

  • options

    類型:字符串,只有省略操作符後可以不加單引號

    • i

      忽略大小寫

      文檔

      { "_id" : 100, "sku" : "abc123", "description" : "Single line description." }
      { "_id" : 101, "sku" : "abc789", "description" : "First line\nSecond line" }
      { "_id" : 102, "sku" : "xyz456", "description" : "Many spaces before     line" }
      { "_id" : 103, "sku" : "xyz789", "description" : "Multiple\nline description" }
      

      查詢

      db.products.find( { sku: { $regex: /^ABC/i } } )
      

      匹配結果

      { "_id" : 100, "sku" : "abc123", "description" : "Single line description." }
      { "_id" : 101, "sku" : "abc789", "description" : "First line\nSecond line" }
      
    • m

      • 對於包含錨點的模式(例如 ^ 表示開始,$ 表示結束)

        文檔

        { "_id" : 100, "sku" : "abc123", "description" : "Single line description." }
        { "_id" : 101, "sku" : "abc789", "description" : "First line\nSecond line" }
        { "_id" : 102, "sku" : "xyz456", "description" : "Many spaces before     line" }
        { "_id" : 103, "sku" : "xyz789", "description" : "Multiple\nline description" }
        

        查詢

        db.products.find( { description: { $regex: /^S/, $options: 'm' } } )
        
        • 當數據爲多行時,含有\n,設置 m 選項,則每行都單獨匹配,任何一行符合條件即可

          匹配結果爲

          { "_id" : 100, "sku" : "abc123", "description" : "Single line description." }
          { "_id" : 101, "sku" : "abc789", "description" : "First line\nSecond line" }
          
        • 當數據爲多行時,含有\n,沒有設置 m 選項,則按一行進行匹配

          匹配結果爲

          { "_id" : 100, "sku" : "abc123", "description" : "Single line description." }
          
      • 對於不包含錨點的模式,或字符串沒有分行,則按一行進行匹配, 設置 m 選項不起作用

        db.products.find( { description: { $regex: /S/ } } )
        
        • 正則表達式不包含 ^ 或 $

        • 匹配的結果爲

          { "_id" : 100, "sku" : "abc123", "description" : "Single line description." }
          { "_id" : 101, "sku" : "abc789", "description" : "First line\nSecond line" }
          
    • x

      忽略空格

      使用x選項忽略空格和註釋 (在匹配模式中以#開始,以\n結束)

      文檔

      { "_id" : 100, "sku" : "abc123", "description" : "Single line description." }
      { "_id" : 101, "sku" : "abc789", "description" : "First line\nSecond line" }
      { "_id" : 102, "sku" : "xyz456", "description" : "Many spaces before     line" }
      { "_id" : 103, "sku" : "xyz789", "description" : "Multiple\nline description" }
      

      查詢

      var pattern = "abc #category code\n123 #item number"
      db.products.find( { sku: { $regex: pattern, $options: "x" } } ) //=> pattern = "abc123"
      

      匹配結果

      { "_id" : 100, "sku" : "abc123", "description" : "Single line description." }
      
    • s

      允許. 匹配所有的字符,包括換行符

      當數據爲多行時,含有\n,將多行視爲一行,換行符\n 被視爲普通字符

      文檔

      { "_id" : 100, "sku" : "abc123", "description" : "Single line description." }
      { "_id" : 101, "sku" : "abc789", "description" : "First line\nSecond line" }
      { "_id" : 102, "sku" : "xyz456", "description" : "Many spaces before     line" }
      { "_id" : 103, "sku" : "xyz789", "description" : "Multiple\nline description" }
      

      查詢

      db.products.find( { description: { $regex: /m.*line/, $options: 'si' } } )
      

      匹配結果爲

      { "_id" : 102, "sku" : "xyz456", "description" : "Many spaces before     line" }
      { "_id" : 103, "sku" : "xyz789", "description" : "Multiple\nline description" }
      
      • .匹配換行符,視爲一行

      不設置 s 選項,則匹配結果爲

      { "_id" : 102, "sku" : "xyz456", "description" : "Many spaces before     line" }
      
      • 換行符無法匹配,視爲多行

$regex vs. /pattern/ Syntax:{}

  • 在 $in 操作符中,只能使用 JS正則對象表達式

    { name: { $in: [ /^acme/i, /^ack/ ] } }
    
  • 以逗號分隔的多查詢條件列表中,使用 $regex 正則操作符表達式

    { name: { $regex: /acme.*corp/i, $nin: [ 'acmeblahcorp' ] } }
    { name: { $regex: /acme.*corp/, $options: 'i', $nin: [ 'acmeblahcorp' ] } }
    { name: { $regex: 'acme.*corp', $options: 'i', $nin: [ 'acmeblahcorp' ] } }
    
  • 要使用選項 ixsm,使用 $regex 正則操作符表達式

$where

3.6版本中 $expr 操作符允許在查詢語言中使用聚合表達式,比where執行速度更快,因爲不執行 JavaScript 代碼,應首選 $expr

  • 在查詢語言中使用 JavaScript 表達式

    使用 $where 操作符將包含 JavaScript表達式的字符串 或 完整的JavaScript函數傳遞給查詢系統

  • 集合中的每個文檔都會執行 JavaScript表達式

  • 在 JavaScript 表達式中通過 this 或 obj 引用文檔

格式

{ $where: <JavaScript expression>
  • 支持的屬性和方法

    Available Properties Available Functions
    args assert() isNumber() print()
    MaxKey BinData() isObject() printjson()
    MinKey DBPointer() ISODate() printjsononeline()
    DBRef() isString() sleep()
    doassert() Map() Timestamp()
    emit() MD5() tojson()
    gc() NumberInt() tojsononeline()
    HexData() NumberLong() tojsonObject()
    hex_md5() ObjectId() UUID()
    version()

示例

文檔

{
   _id: 12378,
   name: "Steve",
   username: "steveisawesome",
   first_login: "2017-01-01"
}
{
   _id: 2,
   name: "Anya",
   username: "anya",
   first_login: "2001-02-02"
}

查詢

db.players.find( { $where: function() {
   return (hex_md5(this.name) == "9b53e667f30cd329dca1ec9e6a83e994")
} } );
  • $where 操作符的值是一個函數,集合中的每個文檔都會執行該函數

  • 結果

    {
       "_id" : 2,
       "name" : "Anya",
       "username" : "anya",
       "first_login" : "2001-02-02"
    }
    

Geospatial Operators

Array Operators

$all
  • 表示字段的值爲數組類型,且包含所有指定的元素

格式

{ <field>: { $all: [ <value1> , <value2> ... ] } }
  • 值爲 數組類型

示例

  • 跟 $and 轉換

    { tags: { $all: [ "ssl" , "security" ] } }
    

    相當於,分別指定一個 $eq 表達式

    { $and: [ { tags: "ssl" }, { tags: "security" } ] }
    
$elemMatch
  • 表示字段的值爲數組類型,且至少有一個元素符合所有指定的條件
  • 不能與 $where $text 操作符結合使用

格式

{ <field>: { $elemMatch: { <query1>, <query2>, ... } } }
  • 如果只指定一個條件,則使用 $eq 較好

示例

  • 元素匹配

    { _id: 1, results: [ 82, 85, 88 ] }
    { _id: 2, results: [ 75, 88, 89 ] }
    

    查找

    db.scores.find(
       { results: { $elemMatch: { $gte: 80, $lt: 85 } } }
    )
    
    • 表示 results 數組中至少有一個元素滿足 80 <= x < 85
$size

Bitwise Operators

Projection Operators

$
$elemMatch
$slice

Update Operators

https://docs.mongodb.com/manual/reference/operator/update-field/

  • 更新操作中的一些操作符

Field Update Operators

  • 更新操作中對字段的操作符
$currentDate
$inc

increments 增長

  • 對指定字段的值進行加減運算
  • 如果字段不存在,則會新增該字段,值爲指定的值
  • 如果對值爲null的字段進行運算,會報錯
  • 針對單個文檔的原子操作

格式

{ $inc: { <field1>: <amount1>, <field2>: <amount2>, ... } }
  • amount 可以是正數 或 負數
$min
$max
$mul
$rename
  • 更改指定字段名

  • 如果 newName 已經存在與文檔中,則會將該字段刪除,然後再將指定字段名修改爲 newName

    相當於先對 old name 和 new name 執行 $unset 操作,然後再對 new name 執行 $set 操作

  • 重命名的字段在文檔中的順序可能會改變

  • 如果指定字段不存在,則什麼都不做

  • 對於嵌入文檔中的字段,$rename操作符可以重命名這些字段,也可以將字段移進或移出嵌入文檔。如果這些字段在數組元素中,則$rename不起作用

    • 重命名,則 newName 也需要使用點表示法引用外層文檔

      db.students.update( { _id: 1 }, { $rename: { "name.first": "name.fname" } } )
      
    • 移動,則 newName 不需要用點表示法引用外層文檔

      db.students.update( {_id:1}, { $rename: { "name.first":"fname" } })
      

      將 fname 移動到頂層

格式

{$rename: { <field1>: <newName1>, <field2>: <newName2>, ... } }
  • newName 必須與已經存在的字段名不同
  • newName 類型是 字符串,需要加引號

示例

文檔

db.students.insert([
{
  "_id": 1,
  "alias": [ "The American Cincinnatus", "The American Fabius" ],
  "mobile": "555-555-5555",
  "nmae": { "first" : "george", "last" : "washington" }
},
{
  "_id": 2,
  "alias": [ "My dearest friend" ],
  "mobile": "222-222-2222",
  "nmae": { "first" : "abigail", "last" : "adams" }
},
{
  "_id": 3,
  "alias": [ "Amazing grace" ],
  "mobile": "111-111-1111",
  "nmae": { "first" : "grace", "last" : "hopper" }
}
])
  • 重命名

    db.students.updateMany(
    {},
    {$rename:{nmae:'name'}}
    )
    
  • 移動字段

    db.students.update(
    {_id:1},
    { $rename: { "name.first":"fname" } }
    )
    
    • 將 "name.first" 字段移動到外面,並重命名爲 fname

      結果爲

      {
          "_id": 1,
          "alias": ["The American Cincinnatus", "The American Fabius"],
          "mobile": "555-555-5555",
          "name": {
              "last": "washington"
          },
          "fname": "george"
      }
      
$set
  • 替換指定字段的值
  • 如果指定字段不存在,則新增該字段,值爲指定的值(前提是不違反類型約束)
  • 如果指定字段不存在,且爲嵌套字段點表示法,則創建該嵌套文檔以及字段,值爲指定的值(前提同上)
  • 如果指定了多個字段,則會更新或新增多個字段

格式

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

若指定子文檔或數組中的字段,則使用點表示法

數組

  • 指定 contribs 中第三個元素,則表示爲 contribs.2

    {
       ...
       contribs: [ "Turing machine", "Turing test", "Turingery" ],
       ...
    }
    

子文檔

  • 指定 last 字段,則表示爲 name.last

    指定 number 字段,則表示爲 contact.phone.number

    {
       ...
       name: { first: "Alan", last: "Turing" },
       contact: { phone: { type: "cell", number: "111-222-3333" } },
       ...
    }
    
  • 一級字段,不需要用雙引號
  • 多級字段,例如數組元素、子文檔,需要用雙引號

示例

文檔

{
  _id: 100,
  sku: "abc123",
  quantity: 250,
  instock: true,
  reorder: false,
  details: { model: "14Q2", make: "xyz" },
  tags: [ "apparel", "clothing" ],
  ratings: [ { by: "ijk", rating: 4 } ]
}

更新操作

db.products.update(
   { _id: 100 },
   { $set:
      {
        quantity:500,
        "details.make":"zzz",
        "tags.1": "rain gear",
        "ratings.0.rating": 2
      }
   }
)
$unset
  • 刪除指定的字段
  • 如果字段不存在,則 $unset 什麼事也不做
  • 當與$一起用於匹配數組元素時,$unset將匹配元素替換爲null,而不是從數組中刪除。此行爲保持數組大小和元素位置的一致性。

格式

{ $unset: { <field1>: "", ... } }
  • 字段的值("")不影響操作,一般用空字符串代替
  • 可以刪除多個,用逗號隔開
  • 嵌入式文檔或數組中的字段使用點表示法.
$setOnInsert

Array Update Operators

$
  • 位置操作符,代表某個元素的位置(下標)

    不需要指明具體的元素下標

  • 當用於更新操作時

    1. $ 代表匹配更新條件的第一個元素下標

    2. 數組字段必須作爲更新條件之一

      通過對數組的操作,確定符合數組操作的第一個元素

      雖然查詢結果返回的是整個文檔,但是在執行數組的操作時,會記錄第一個符合數組過濾條件的元素

示例

  • 元素類型爲普通值時{ "<array>.$" : value } }

    db.students.insert([
       { "_id" : 1, "grades" : [ 85, 80, 80 ] },
       { "_id" : 2, "grades" : [ 88, 90, 92 ] },
       { "_id" : 3, "grades" : [ 85, 100, 90 ] }
    ])
    

    更新

    db.students.updateOne(
       { grades: {$gte:89} },
       { $set: { "grades.$" : 89 } }
    )
    
    • 數組字段 grades 作爲更新條件之一

      通過對數組的操作 {$gte:89},確定符合條件的文檔以及第一個符合數組過濾條件的元素

    • 在更新操作中用$代表符合條件的元素

    • 更新 _id 爲1,grades數組中包含 80 的文檔,並將符合數組過濾條件的第一個元素值改爲 89

      第一個文檔的grades變爲 [85, 82, 80]

  • 元素類型爲子文檔時{ "array.$.field" : value } }

    {
      _id: 4,
      grades: [
         { grade: 80, mean: 75, std: 8 },
         { grade: 85, mean: 90, std: 5 },
         { grade: 85, mean: 85, std: 8 }
      ]
    }
    

    更新

    db.students.updateOne(
       { _id: 4, "grades.grade": 85 },
       { $set: { "grades.$.std" : 6 } }
    )
    
$[]

New in version 3.6.

  • 所有位置操作符,代表所有元素的位置(下標)
  • 更新操作會作用於匹配條件的 數組中的 所有元素
  • 官方文檔中都添加了multi: true 選項,但是測試不加也可以作用於所有元素

格式

db.collection.updateMany(
   { <query conditions> },
   { <update operator>: { "<array>.$[]" : value } }
)

示例

  • 元素類型爲普通值時 { "<array>.$[]" : value } }

    { "_id" : 1, "grades" : [ 85, 82, 80 ] }
    { "_id" : 2, "grades" : [ 88, 90, 92 ] }
    { "_id" : 3, "grades" : [ 85, 100, 90 ] }
    

    更新

    db.students.update(
       { },
       { $inc: { "grades.$[]": 10 } },
       { multi: true }
    )
    
    • 更新條件爲空,則更新所有文檔
    • 更新所有文檔中 grades 數組中的每個元素(增加10)
  • 元素類型爲子文檔時{ "array.$[].field" : value } }

    {
       "_id" : 1,
       "grades" : [
          { "grade" : 80, "mean" : 75, "std" : 8 },
          { "grade" : 85, "mean" : 90, "std" : 6 },
          { "grade" : 85, "mean" : 85, "std" : 8 }
       ]
    }
    {
       "_id" : 2,
       "grades" : [
          { "grade" : 90, "mean" : 75, "std" : 8 },
          { "grade" : 87, "mean" : 90, "std" : 5 },
          { "grade" : 85, "mean" : 85, "std" : 6 }
       ]
    }
    

    更新

    db.students2.update(
       { },
       { $inc: { "grades.$[].std" : -2 } },
       { multi: true }
    )
    
    • 更新所有文檔中grades數組中的每個元素所代表的子文檔中的 std 字段(增加 -2)
  • 結合過濾位置操作符

    db.students3.insert([
       { "_id" : 1,
          "grades" : [
            { type: "quiz", questions: [ 10, 8, 5 ] },
            { type: "quiz", questions: [ 8, 9, 6 ] },
            { type: "hw", questions: [ 5, 4, 3 ] },
            { type: "exam", questions: [ 25, 10, 23, 0 ] },
          ]
       }
    ])
    

    更新

    db.students3.update(
       {},
       { $inc: { "grades.$[].questions.$[score]": 2 } },
       { arrayFilters: [  { "score": { $gte: 8 } } ], multi: true}
    )
    
    • 更新所有文檔中的grades數組中的每個元素所代表的子文檔中的 questions 數組中的符合條件的元素
    • 使用 arrayFilters 設定數組元素的的過濾條件
$[ <identifier> ]

New in version 3.6.

  • 過濾位置操作符,代表符合條件的元素的位置
  • 更新操作會作用於匹配條件的 數組中的 符合條件元素
  • 結合 arrayFilters 選項使用
  • <標識符> 必須以小寫字母開頭,且只包含字母、數字

格式

db.collection.updateMany(
   { <query conditions> },
   { <update operator> : { "<array>.$[<identifier>]" : value } },
   { arrayFilters: [ { <identifier>: <condition> } ] }
)

示例

  • 元素類型爲普通值時 { "<array>.$[<identifier>]" : value } }

    { "_id" : 1, "grades" : [ 95, 92, 90 ] }
    { "_id" : 2, "grades" : [ 98, 100, 102 ] }
    { "_id" : 3, "grades" : [ 95, 110, 100 ] }
    

    更新

    db.students.update(
       { },
       { $set: { "grades.$[element]" : 100 } },
       { multi: true,
         arrayFilters: [ { "element": { $gte: 100 } } ]
       }
    )
    
    • 更新操作中用 grades.$[element] 表示符合條件的元素
    • arrayFilters 中用 element 代表元素,設定過濾條件
  • 元素類型爲子文檔時{ "array.$[<identifier>].field" : value }

    {
       "_id" : 1,
       "grades" : [
          { "grade" : 80, "mean" : 75, "std" : 6 },
          { "grade" : 85, "mean" : 90, "std" : 4 },
          { "grade" : 85, "mean" : 85, "std" : 6 }
       ]
    }
    {
       "_id" : 2,
       "grades" : [
          { "grade" : 90, "mean" : 75, "std" : 6 },
          { "grade" : 87, "mean" : 90, "std" : 3 },
          { "grade" : 85, "mean" : 85, "std" : 4 }
       ]
    }
    

    更新

    db.students2.update(
       { },
       { $set: { "grades.$[elem].mean" : 100 } },
       {
         multi: true,
         arrayFilters: [ { "elem.grade": { $gte: 85 } } ]
       }
    )
    
    • 更新所有文檔中的grades數組中的符合條件的元素代表的子文檔中的 mean 字段
    • 符合條件的元素指,子文檔中grade字段的值大於等於85
  • 嵌套數組

    db.students3.insert(
       { "_id" : 1,
          "grades" : [
            { type: "quiz", questions: [ 10, 8, 5 ] },
            { type: "quiz", questions: [ 8, 9, 6 ] },
            { type: "hw", questions: [ 5, 4, 3 ] },
            { type: "exam", questions: [ 25, 10, 23, 0 ] },
    
          ]
       }
    )
    

    更新

    db.students3.update(
       {},
       { $inc: { "grades.$[t].questions.$[score]": 2 } },
       { arrayFilters: [ { "t.type": "quiz" } , { "score": { $gte: 8 } } ], multi: true}
    )
    
    • 更新所有文檔中的grades數組中的符合條件的元素代表的子文檔中的questions數組中的符合條件的元素
    • 條件1 { "t.type": "quiz" } ;條件2 { "score": { $gte: 8 } }
$addToSet
$pop
  • 刪除數組中的第一項或最後一項
    • 指定值爲 -1,則刪除第一項
    • 指定值爲 1, 則刪除最後一項
  • 如果刪除了數組中最後一個元素,則字段值爲空數組[ ]
  • 如果指定字段的值不是數組,則操作失敗

格式

{ $pop: { <field>: <-1 | 1>, ... } }

示例

文檔

{ _id: 1, scores: [ 8, 9, 10 ] }

更新

db.students.update( { _id: 1 }, { $pop: { scores: -1 } } )
  • 刪除第一個元素

  • 結果爲

    { _id: 1, scores: [ 9, 10 ] }
    
$pull
  • 刪除數組中指定的值 或 所有符合條件的值

  • 如果指定了 condition,且數組元素是嵌套文檔,$pull 操作符會將每個嵌套子文檔視爲頂級文檔進行 condition 匹配

    • 如果是兩層嵌套,不需要通過 $elemMatch 來指定內層字段的條件
    • 如果是三層嵌套,則需要通過 $elemMatch 來指定內層字段的條件
  • 如果指定的值 value 是數組,則 $pull 操作符將刪除與 value 完全匹配的元素,包括元素順序

  • 如果指定的值 value 是文檔,則 $pull 操作符將刪除與 value 具有相同字段和值的元素,忽略字段順序

格式

{ $pull: { <field1>: <value|condition>, <field2>: <value|condition>, ... } }
  • condition 類型爲操作符表達式文檔
  • value 類型爲操作符表達式文檔

示例

  • 刪除指定值

    db.stores.update(
        { },
        { $pull: { fruits: { $in: [ "apples", "oranges" ] }, vegetables: "carrots" } },
        { multi: true }
    )
    
    • value 爲 $in 操作符表達式 或 字符串($eq 操作符表達式)
  • 刪除滿足條件的值

    db.profiles.update( { _id: 1 }, { $pull: { votes: { $gte: 6 } } } )
    
    • condition 爲 $gte 操作符表達式
  • 兩層嵌套:數組元素是子文檔

    {
       _id: 1,
       results: [
          { item: "A", score: 5 },
          { item: "B", score: 8, comment: "Strongly agree" }
       ]
    }
    {
       _id: 2,
       results: [
          { item: "C", score: 8, comment: "Strongly agree" },
          { item: "B", score: 4 }
       ]
    }
    

    更新

    db.survey.update(
      { },
      { $pull: { results: { score: 8 , item: "B" } } },
      { multi: true }
    )
    
    • condition 爲 子文檔 { score: 8 , item: "B" }

    • 不需要通過 $elemMatch 指定

      db.survey.update(
        { },
        { $pull: { results: { $elemMatch: { score: 8 , item: "B" } } } },
        { multi: true }
      )
      

      不會刪除任何元素

  • 三層嵌套:數組元素是子文檔,子文檔字段是數組

    {
       _id: 1,
       results: [
          { item: "A", score: 5, answers: [ { q: 1, a: 4 }, { q: 2, a: 6 } ] },
          { item: "B", score: 8, answers: [ { q: 1, a: 8 }, { q: 2, a: 9 } ] }
       ]
    }
    {
       _id: 2,
       results: [
          { item: "C", score: 8, answers: [ { q: 1, a: 8 }, { q: 2, a: 7 } ] },
          { item: "B", score: 4, answers: [ { q: 1, a: 0 }, { q: 2, a: 8 } ] }
       ]
    }
    

    更新

    db.survey.update(
      { },
      { $pull: { results: { answers: { $elemMatch: { q: 2, a: { $gte: 8 } } } } } },
      { multi: true }
    )
    
$push
  • 給數組末尾增加一個元素
  • 如果文檔中不存在指定的字段,則會新增該字段,值爲僅包含指定值的數組
  • 如果指定字段的值不是數組,則操作失敗
  • 如果指定的值是數組,則視爲一個元素添加到指定字段數組中

格式

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

結合修飾符

{ $push: { <field1>: { <modifier1>: <value1>, ... }, ... } }

示例

  • 結合 $each 修飾符,將數組中的元素分別添加到指定字段

    db.students.update(
       { name: "joe" },
       { $push: { scores: { $each: [ 90, 92, 85 ] } } }
    )
    
    • 用 $each 修飾要添加到指定字段的數組(值)
  • 結合 $each $sort $slice

    {
       "_id" : 5,
       "quizzes" : [
          { "wk": 1, "score" : 10 },
          { "wk": 2, "score" : 8 },
          { "wk": 3, "score" : 5 },
          { "wk": 4, "score" : 6 }
       ]
    }
    

    更新

    db.students.update(
       { _id: 5 },
       {
         $push: {
           quizzes: {
              $each: [ { wk: 5, score: 8 }, { wk: 6, score: 7 }, { wk: 7, score: 6 } ],
              $sort: { score: -1 },
              $slice: 3
           }
         }
       }
    )
    
    • $each

      將數組 [ { wk: 5, score: 8 }, { wk: 6, score: 7 }, { wk: 7, score: 6 } ] 中的元素分別添加到 quizzes 數組中

    • $sort

      將數組中的所有元素按照 score 字段的值降序排列

    • $slice

      提出數組中前3個元素

$pullAll
$each
$position
$slice
$sort

Query Modifiers

$natural
  • 自然順序
  • 與 cursor.hint() 聯合使用,執行集合掃描以按自然順序返回文檔。
  • 不能在 視圖 中使用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章