連接
標準 URI 連接語法
通常,可以設定標準的 URI 連接語法,作為連接配置:
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
mongodb://: 固定的格式,即指定當前的 URI 是標準的 MongoDB 連接語法username:password@: 可選項,如果設定,在連接資料庫服務器之后,驅動會嘗試登錄這個資料庫host1: 必須的,至少指定一個 host,它指定了要連接服務器的地址,如果要連接副本及集,需要指定多個主機地址portX: 可選的指定埠,如果不填,默認為27017/database: 如果指定賬號和密碼,連接并驗證登錄指定資料庫,若不指定,默認打開 test 資料庫?options: 連接選項,如果沒有指定資料庫,則前面需要加上/,所有連接選項都是鍵值對name=value,鍵值對之間通過&或;隔開
連接選項
標準的連接格式包含了多個選項,如下所示:
replicaSet=name: 驗證副本集的名稱slaveOk=true|false: 選擇連接主服務器的方式true: 表示有從服務器,當connect=direct時會連接第一臺機器,即使這臺不是主服務器;當connect=replicaSet時會發送所有的寫請求到主并且把讀請求分布在其他從服務器false: 表示無從服務器,當connect=direct時會自動找尋主服務器;當connect=replicaSet時僅連接主服務器,并且所有的讀寫命令都連接到主服務器
safe=true|false: 設定為true時,在執行更新操作之后,驅動都會發送getLastError命令來確保更新成功w=n: 驅動添加{w: n}到getLastError命令,應用于safe=truewtimeoutMS=ms: 驅動添加{wtimeout: ms}到getLastError命令,應用于safe=truefsync=true|false: 驅動添加{fsync: true}到getLastError命令,應用于safe=truejournal=true|false: 如果設定為true,同步到日志(在提交到資料庫前寫入到物體中),應用于safe=trueconnectTimeoutMS=ms: 可以打開連接的時間socketTimeoutMS=ms: 發送和接受 socket 的時間
連接命令格式
使用 mongosh 連接 MongoDB 時,也支持命令選項的方式添加配置:
--host arg: 指定資料庫地址--port arg: 指定資料庫埠-u [ --username ] arg: 鑒權的賬號-p [ --password ] arg: 鑒權的密碼
插入檔案
插入校驗
MongoDB 會對要插入的資料進行最基本的檢查:檢查檔案的基本結構,如缺少 _id 鍵會自動添加一個、是否包含非 UTF-8 字符、是否使用了無法識別的型別、檢查檔案大小等,
其中,檢查檔案大小主要因為 MongoDB 限制了所有檔案必須小于 16MB,主要是為了防止不良的模式設計并確保性能上的一致,
要查看檔案的 BSON 大小,可以在 shell 中執行 Object.bsonsize(doc) 查看位元組大小,
單個插入
官方檔案:db.collection.insertOne() — MongoDB Manual
db.collection.insertOne(
<document>,
{
writeConcern: <document>
}
)
批量插入
官方檔案:db.collection.insertMany() — MongoDB Manual
db.collection.insertMany(
[ <document 1> , <document 2>, ... ],
{
writeConcern: <document>,
ordered: <boolean>
}
)
通過傳輸 ordered=true 可以確保檔案按提供的順序插入,指定為 false 則允許 MongoDB 重新排列插入的順序以提高性能,默認為 true 值,
以有序插入的方式使用 insertMany 出現錯誤將會阻塞后續的插入動作,無需插入的方式則不管其他插入是否出現了錯誤,
洗掉檔案
單個洗掉
官方檔案:db.collection.deleteOne() — MongoDB Manual
db.collection.deleteOne(
<filter>,
{
writeConcern: <document>,
collation: <document>,
hint: <document|string> // Available starting in MongoDB 4.4
}
)
使用 hint 引數可以指定 filter 查詢時命中的索引,這對于復雜的索引結構時可以提升部分效率,
批量洗掉
官方檔案:db.collection.deleteMany() — MongoDB Manual
db.collection.deleteMany(
<filter>,
{
writeConcern: <document>,
collation: <document>,
hint: <document|string> // Available starting in MongoDB 4.4
}
)
單個洗掉并回傳
官方檔案:db.collection.findOneAndDelete() — MongoDB Manual
db.collection.findOneAndDelete(
<filter>,
{
writeConcern: <document>,
projection: <document>,
sort: <document>,
maxTimeMS: <number>,
collation: <document>
}
)
更新檔案
更新檔案是原子操作:如果兩個更新同時發生,那么首先到達服務器的更新會先被執行,然后再執行下一個更新,
因此,相互沖突的更新可以安全地迅速接連完成,而不會破壞任何檔案:最后一次更新將“成功”,如果不想使用默認行為,則可以考慮使用檔案版本控制模式,
單個更新
官方檔案:db.collection.updateOne() — MongoDB Manual
db.collection.updateOne(
<filter>,
<update>,
{
upsert: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
hint: <document|string> // Available starting in MongoDB 4.2.1
}
)
在更新檔案的時候,比較需要注意的事 upsert 的使用,其是一種特殊型別的更新:如果找不到與篩選條件相匹配的檔案,則會以這個條件和更新檔案為基礎來創建一個新檔案;如果找到了匹配的檔案,則進行正常的更新,
因此,使用 upsert 的好處就是,可以使用同一套代碼創建和更新檔案,
使用 upsert 時就涉及到一個 $setOnInsert 運算子,它的作用是,只會在插入檔案時設定欄位的值,在后續的更新時不對其進行更改,
批量更新
官方檔案:db.collection.updateMany() — MongoDB Manual
db.collection.updateMany(
<filter>,
<update>,
{
upsert: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
hint: <document|string> // Available starting in MongoDB 4.2.1
}
)
單個替換
官方檔案:db.collection.replaceOne() — MongoDB Manual
db.collection.replaceOne(
<filter>,
<replacement>,
{
upsert: <boolean>,
writeConcern: <document>,
collation: <document>,
hint: <document|string> // Available starting in 4.2.1
}
)
replaceOne 和 updateOne 操作的區別在于,updateOne 可以更新檔案中部分鍵的值,而 replaceOne 的作用是直接將整個檔案都替換掉,通常是建議使用 updateOne 而不是 replaceOne,
單個更新并回傳
官方檔案:db.collection.findOneAndUpdate() — MongoDB Manual
db.collection.findOneAndUpdate(
<filter>,
<update document or aggregation pipeline>, // Changed in MongoDB 4.2
{
projection: <document>,
sort: <document>,
maxTimeMS: <number>,
upsert: <boolean>,
returnDocument: <string>,
returnNewDocument: <boolean>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ]
}
)
使用 findOneAndUpdate 而不是 updateOne 的最大目的莫過于使用 findOneAndUpdate 可以回傳更新前后檔案內容,
通過設定 returnNewDocument 的值為 true 可以回傳更新后的檔案,為 false 時可以回傳更新前的檔案,
單個替換并回傳
官方檔案:db.collection.findOneAndReplace() — MongoDB Manual
db.collection.findOneAndReplace(
<filter>,
<replacement>,
{
projection: <document>,
sort: <document>,
maxTimeMS: <number>,
upsert: <boolean>,
returnDocument: <string>,
returnNewDocument: <boolean>,
collation: <document>
}
)
更新運算子
官方檔案:Update Operators — MongoDB Manual
對于如 updateOne、updateMany、findOneAndUpdate 等更新操作,MongoDB 提供了原子的更新運算子支持只更新部分資料,
運算子支持以 { <operator>: { <field>: <value>,... } } 的方式使用,并且可以同時使用多個運算子,
為避免出現歧義,不建議對同一個屬性同時使用不同的運算子,
欄位
$currentDate: 將指定鍵設定為當前時間$inc: 對數字型別的鍵做遞增操作$min: 會比較原始值和更新值,并設定成較小值$max: 會比較原始值和更新值,并設定成較大值$mul: 對數字型別的鍵做乘法操作$rename: 修改指定鍵的名稱$set: 將指定鍵設定為指定值$setOnInsert: 與upsert配合使用,如果更新導致檔案插入,則設定欄位的值,對修改現有檔案的更新操作無效$unset: 洗掉指定鍵
陣列
$: 充當占位符,更新與查詢條件匹配的第一個元素$[]: 充當占位符,為匹配查詢條件的檔案更新陣列中的所有元素$[<identifier>]: 充當占位符,為匹配查詢條件的檔案更新與arrayFilters條件匹配的所有元素$addToSet: 僅當集合中不存在該元素時,才將元素添加到陣列中$pop: 傳{ $pop: { field: 1 } }表示洗掉陣列中的最后一項,傳-1時表示洗掉第一項$pull: 洗掉與指定查詢匹配的所有陣列元素$push: 新增一項到陣列中$pullAll: 洗掉列出的所有陣列元素
陣列內層
$each: 使用$push或$addToSet運算子時,增加此運算子可以批量添加元素$position: 與$each配合使用,可以指定添加元素的位置$slice: 與$each配合使用,防止陣列的增長超過某個大小,傳正數表示從左到右截斷$sort: 與$each配合使用,對添加完元素的陣列進行排序
位運算
$bit: 支持對整數值進行按位 AND、OR 或 XOR 更新,通過使用 { $bit: { <field>: { <and|or|xor>: <int> } } } 完成更新,
批量寫操作
官方檔案:db.collection.bulkWrite() — MongoDB Manual
MongoDB 提供了 bulkwrite 命令支持批量執行命令,批處理時在一定程度上減少了網路互動的損耗,
db.collection.bulkWrite(
[ <operation 1>, <operation 2>, ... ],
{
writeConcern: <document>,
ordered: <boolean>
}
)
支持的以下操作:
insertOneupdateOneupdateManyreplaceOnedeleteOnedeleteMany
查詢檔案
單個查詢
官方檔案:db.collection.findOne() — MongoDB Manual
db.collection.findOne(query, projection, options)
第一個引數是查詢條件,可以使用鍵值對的方式指定需要匹配的條件,多個鍵之間是 AND 的關系,
第二個引數用于僅回傳指定的鍵,既可以節省網路傳輸的資料量,也可以減少客戶端解碼檔案的時間和記憶體消耗,
第三個引數可以指定查詢到可選項,這些選項會修改查詢行為和回傳結果的方式,更多查看 官方檔案,
批量查詢
官方檔案:db.collection.find() — MongoDB Manual
db.collection.find(query, projection, options)
資料庫會使用游標回傳 find 的執行結果,
對于游標,客戶端可以限制結果的數量,跳過一些結果,按任意方向的任意鍵組合對結果進行排序等操作,更多查詢 官方檔案,
下述是一些常用的游標方法:
count(): 統計游標參考的檔案數量hasNext(): 查詢是否有下一個結果hint(index): 指定游標命中的索引limit(number): 限制回傳結果的數量next(): 回傳下一個搜索結果size(): 回傳應用skip()和limit()之后的查詢數量skip(number): 控制跳過一定的數量,跳過大量資料會比較慢sort(sort): 使用鍵值對的方式對搜索結果進行排序
在服務器端,游標會占用記憶體的資源,通常在以下情況會終止游標及進行隨后的清理:
- 當游標遍歷完成匹配的結果時,它會清除自身
- 當游標超出客戶端的作用域時,驅動程式會向資料庫發送終止游標的信號
- 當游標達到 10 分鐘沒有使用時,資料庫游標會被自動銷毀
查詢運算子
官方檔案:Query and Projection Operators — MongoDB Manual
同樣的,設定查詢條件時,MongoDB 提供了查詢運算子支持更多的查詢方式,
比較運算子
$eq: 回傳等于指定值的結果,等同{ <field>: <value> }的顯式表示$gt: 回傳大于指定值的結果$gte: 回傳大于等于指定值的結果$in: 回傳等于指定陣列中任意一個值的結果,對于一個鍵匹配多個值,$in比$or更方便$lt: 回傳小于指定值的結果$lte: 回傳小于等于指定值的結果$ne: 回傳不等于指定值的結果$nin: 回傳不等于指定陣列中任意一個值的結果
邏輯運算子
$and: 回傳同時符合查詢子句要求的結果$not: 元運算子,匹配不符合查詢陳述句要求的結果$nor: 回傳不能同時符合查詢子句要求的結果$or: 回傳與任意一個查詢子句的條件匹配的結果
對于普通的 $and 型別查詢,我們總是希望盡可能用最少的引數來限定結果的范圍,而 $or 型別查詢則相反,如果第一個引數能夠匹配盡可能多的檔案,則其效率最高,
元素運算子
$exists: 判斷指定鍵是否存在,回傳符合要求的結果$type: 判斷指定鍵的資料型別,回傳符合要求的結果(好的模式設計不應該出現不同型別)
運算式運算子
$expr: 允許使用聚合運算式,適合用在一些比較復雜的查詢陳述句$jsonSchema: 根據給定的 JSON 模式驗證檔案,回傳符合要求的結果$mod: 指定鍵的值執行模運算,回傳符合要求的結果$regex: 使用正則運算式對指定鍵做匹配,MongoDB 可以利用索引來查詢前綴正則運算式,但不能用于不區分大小寫的搜索$text: 對使用文本索引的欄位內容執行文本搜索,可以作為一個簡易的搜索引擎使用$where: 允許在查詢時執行任意 JavaScript 代碼(性能較差,盡可能使用$expr代替)
陣列運算子
$all: 匹配包含查詢中指定的所有元素的陣列$elemMatch: 用于強制將查詢子句與單個陣列元素進行匹配$size: 匹配指定陣列長度大小的結果
投影運算子
投影運算子針對的是查詢陳述句的第二個引數,即回傳的結果,
$: 僅回傳陣列中與查詢條件匹配的第一個元素$elemMatch: 對回傳結果中的陣列元素做$elemMatch匹配,僅回傳陣列中滿足要求的元素$meta: 與$text運算子配合使用,回傳與檔案關聯的元資料,可以回傳匹配分數,或者索引鍵$slice: 對回傳結果中的陣列做截取回傳
特殊的 null 值
在 MongoDB 中,null 是一個比較特殊的值,它可以與自身匹配,也就是說了,通過 { field: null } 可以查詢出 field 鍵為 null 的檔案,
不過,更特殊的是,null 同樣會匹配缺少這個鍵值的檔案,也就是說,{ field: null } 可以查詢出不包含 field 鍵的檔案,
如果僅想匹配鍵值為 null 的檔案,則需要檢查該鍵的值是否為 null,并且通過 $exists 條件確認該鍵已存在,如 { field: { $eq: null, $exists: true } } 就是這樣的查詢條件組,
首發于翔仔的個人博客,點擊查看更多,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/535276.html
標籤:其他
