深入學習 Read 操作
Methods, Filters & Operators
在 mongosh 讀取資料時,根據使用運算子與否,查詢指令大致可分為兩種結構。
無運算子的讀取操作
db.collection_name.find({ field: value })
有運算子的讀取操作
db.collection_name.find({ field: { $Operator: value } })
Understanding "findOne()" & "find()"
比較以下指令的差異
# 以下兩行指令會取回 Collection 的第一筆資料
db.collection_name.findOne()
db.collection_name.findOne({})
# 取回符合條件的第一筆資料
db.collection_name.findOne({field: value})
# 取回 Collection 的所有資料
db.collection_name.find()
# 取回符合條件的所有資料
db.collection_name.find({field: value})
Working with Comparison Operators
以下是幾個 Query Selectors。
- $gt
Matches values that are greater than a specified value. - $lte
Matches values that are less than or equal to a specified value. - $in
Matches any of the values specified in an array. - $ne
Matches all values that are not equal to a specified value.
Querying Embedded Fields & Arrays
以嵌入式 Document 為篩選條件時,需在 filter 使用點記法設定條件。
db.collection_name.find({"key.dotNotation1.dotNotation2...": value})
db.collection_name.find({"key.dotNotation1.dotNotation2...": {$Operator: value}})
如以下範例,查詢標的為陣列時,需注意篩選條件為陣列內元素完全一致或部分一致。
# 取回陣列內元素與 value 完全一致的資料(當 value 為三個元素時,需完全一致)
db.collection_name.find({someArray: [value]})
# 取回陣列內元素含有 value 的資料(當 someArray 的元素包含 value 就算符合篩選條件 )
db.collection_name.find({someArray: value})
"$or" and "$nor"
讀取資料時,可利用 $or 設置多個 filter,如此會取回符合任一 filter 的資料。
db.collection_name.find( { $or: [ { key1: { $Operator: value1 } }, { key2: value2 } ] } )
讀取資料時,可利用 $nor 設置多個 filter,如此會取回不符合所有 filter 的資料。
db.collection_name.find( { $nor: [ { key1: { $Operator: value1 } }, { key2: value2 } ] } )
Understanding the "$and" Operator
讀取資料時,可利用 $and 設置多個 filter,如此會取回符合所有 filter 的資料。
db.collection_name.find( { $and: [ { key1: { $Operator: value1 } }, { key2: value2 } ] } )
以下為簡寫語法,效果等同於使用 $and。
db.collection_name.find( { key1: { $Operator: value1 }, key2: value2 } )
$and 運算子存在的意義
當 filter 的篩選條件為同鍵不同值時,使用簡寫語法將導致既有篩選條件被後來加入的條件覆寫。
因此 $and 仍有存在的必要,亦即簡寫語法並非適用於任何應用情境。
以下列指令為例,最終會取得符合 key1: value2 的資料,
而非既符合 key1: value1 且符合 key1: value2 的資料。
db.collection_name.find( { key1: value1, key1: value2 } )
Using "$not"
$not 運算子必須搭配其他運算子才可使用。
Syntax: { field: { $not: { <operator-expression> } } }
db.collection_name.find( { key: { $not: {$Operator: value} } } )
$not 的使用頻率並不高,因為某些運算子就具有否定意義,例如 $ne、$nor 等。
此外,$not 的語法結構較複雜、易讀性較差,因此使用前最好思考是否有替代方案。
Diving Into Element Operators
$exists 運算子可將 Document 當中是否含有特定 field 當作查詢條件。
Syntax: { field: { $exists: <boolean> } }
db.collection_name.find({ key: { $exists: true } })
db.collection_name.find({ key: { $exists: false, $Operator: value } });
Working with "$type"
$type 運算子可將資料型別當作查詢條件。
Syntax: { field: { $type: <BSON type> } }
# 取回 number 型別的資料
db.collection_name.find({ key: { $type: "number" } })
# 取回型別為 number 或 string 的資料
db.collection_name.find({ key: { $type: ["number", "string"] } })
Understanding Evaluation Operators - "$regex"
$regex 運算子可將正規表達式當作查詢條件。
{ <field>: { $regex: /pattern/, $options: '<options>' } }
{ <field>: { $regex: 'pattern', $options: '<options>' } }
{ <field>: { $regex: /pattern/<options> } }
db.collection_name.find({ key: { $regex: /pattern/ } });
$regex 適合檢索特定字串,但效能並非極佳。
在講究效能的應用情境時,使用 text index 效能更好。
Understanding Evaluation Operators - "$expr"
$expr 搭配其他運算子,可將條件式當作查詢條件,主要用於比對同一 Document 當中不同 field。
但要注意,field 需添加 $。若有必要也可再搭配 $cond 篩選資料。
{ $expr: { <expression> } }
# 基本語法
db.collection_name.find({$expr: {$Operator:["fieldName1", "fieldName2"]}})
# 搭配 $cond
db.collection_name.find({$expr: {$Operator: [{$cond: {if: {$gte: ["$fieldName1", value]}, then: {$subtract: ["$fieldName1", value]}, else: "$fieldName1"}}, "$fieldName2"]}})
Sorting Cursor Results
cursor 可調用 sort 方法,藉此將資料排序。
sort 接受的引數為 {field1: value1, field2: value2,...},其中 value 的值僅接受 1(ASC)或 -1(DESC)
Skipping & Limiting Cursor Results
cursor 可調用 skip 方法,效用類似 SQL 的 OFFSET。 cursor 可調用 limit 方法,效用類似 SQL 的 LIMIT。
db.collection_name.find().skip(整數)
db.collection_name.find().limit(整數)
db.collection_name.find().skip(整數).limit(整數)
cursor 調用 skip、sort、limit 的順序並不影響查詢結果。
Using Projection to Shape our Results
查詢資料時,利用 Projection(投影、選擇欄位)可避免取回不需要的資料。其語法結構如下:
db.collection_name.find({}, {field: value})
value 的值可以是 0 或 1
# 取回 field1 以外的所有欄位
db.collection_name.find({}, { field1: 0 })
# 取回 field1 及 _id(因為 _id 預設取回)
db.collection_name.find({}, { field1: 1 })
# 取回 field1 但不取回 _id
db.collection_name.find({}, { field1: 1, _id: 0 })
Using Projection in Arrays
查詢資料庫並取回陣列型態的資料時,可利用 Projection 取回陣列內的特定元素。
# 找出 arrayField 當中含有元素 value 的 Document,且取出陣列中所有元素(以及預設回傳的 _id)。
db.collection_name.find({arrayField: value}, { arrayField: 1 })
# 找出 arrayField 當中含有元素 value 的 Document,但只從陣列中取出值為 value 的元素(以及預設回傳的 _id)。
db.collection_name.find({arrayField: value}, { "arrayField.$": 1 })
# 找出 arrayField 當中含有元素 value1 的 Document,並且判斷 arrayField 是否含有元素 value2,
# 若有則回傳 value2(以及預設回傳的 _id),若無則回傳 _id。
db.collection_name.find({arrayField: value1}, {arrayField: {$elemMatch: {$eq: value2}}})
Understanding "$slice"
查詢資料庫時可使用 $slice,藉以限制從陣列中取出哪些元素。
傳入 $slice 的使用方法類似 JavaScript 的 slice 函式。
# 找出 arrayField 當中含有元素 value1 的 Document,但只回傳 arrayField 的前兩個值。
db.collection_name.find({ arrayField: value }, { arrayField: { $slice: 2 } })
# 找出 arrayField 當中含有元素 value1 的 Document,
# 但只回傳 arrayField 當中,索引值始於 0 結束於 2 - 1 之間的值(以及預設回傳的 _id)。
db.collection_name.find( { arrayField: value }, { arrayField: { $slice: [0, 2] } } )