拿到有資料的資料庫,一件事情就是要來做資料查詢! 因為現在在MongoDB裡面的資料,都存放在同一個文件 (Document) 中,所以相對於之前我們在寫SQL的時候需要去考量關聯表,現在的查詢就沒有那麼複雜啦 。但是為讓人比較頭痛的事情是 MongoDB 使用大量的大括號,在撰寫的時候務必特別小心括號有沒有對齊,就讓我們開始從最簡單的尋找文檔開始寫吧。
在昨天的文章最後,我們使用了 find 把資料庫所有的東西都印出來。可以這樣做是因為我在呼叫 find 的時候沒有傳入任何資訊,既然沒有任何的塞選條件,自然的就會把所有資料回傳囉。我們用一個新的資料集來回顧一下昨天的指令 (一樣可以打開 MongoDB Compass 下方的 MongoSH Beta)
// 先把資料集叫出來
use sample_training
// 呼叫查詢
db.grades.find()
這邊 db
是 MongoDB 選定的資料庫,接下來選擇資料庫中要查詢的數據集合 Collections,最後呼叫 find ()
做查詢。有時候我們只想要看到一點點的資料,就可以在後面加上 limit()
,括號內的數字表示回傳的限制個數,這部分跟SQL一樣。
db.grades.find().limit(5)
這時候如果我們只想查找學生編號 (student_id) 2 號的同學生成績
db.grades.find({student_id:2})
這時候我們就可以在小括號中放入一個大括號,就可以透過 Key-Value 來查詢,如果想用 Compass來執行,可以在上面的 Filter 放入查詢的過濾條件
讓我們依照class_id 排序,這裡的 1 表示有小到大排序,如果要反過來可以使用 -1 .
db.grades.find({student_id:2}).sort({class_id:1})
到這邊我就假設讀者已經發現 Compass 不果就是把每一個可以串接的小括號放在上面讓你輸入值。接下來我就主要打 MongoDB 的指令,但是讀者可以用 Compass來操作視覺上比較好懂。
如果我們想要找的是 2 號學生在課號91 的成績,我們可以用
db.grades.find({
student_id:2,
class_id:91
})
這時候我把它放在一起,他在過濾的就是文檔中是否同時符合這兩個項目。但是和SQL一樣的地方是我們也可以串接很多個條件並加上各種大於小於:
db.grades.find(
{$and:[
{student_id:2},
{class_id:{$lte:200}}]
})
這邊我們找的是 2 號學生 而且 課號 小於等於 200 的成績,有注意到嗎? 當我寫 $and 的指令,後面帶的是一個 "值",既然JSON 都是 Key-Value pair,最外層就要用大括號框起來。寫最後一個再複雜一點的:
db.grades.find(
{$or:[
{$and:[{student_id:2},{class_id:{$lte:200}}]},
{$and:[{student_id:4},{class_id:{$gte:100}}]}
]})
沒錯你猜對了,我們找的是 2 號學生 而且 課號 小於等於 200 的成績或者是 4 號學生 而且 課號 大於等於 100 的成績
如果我們要找的是再深一層的,我們可以用點和引號來表示
db.grades.find(
{'scores.0.score': {$gte:50},
student_id: {$lte:3}
})
你會發現因為我們要找的值有階層,所以用引號框起來。這裡講的是請你找文檔中,scores 這個Key底下的第0項裡面的score 數值要大於50。
最後補充一件事情,如果寫下
db.grades.find(
{student_id: 3, student_id: 2, student_id: 1})
再同階層存在很多個相同的 Key 但是有不同過濾的 Value,MongoDB 會考量最後一個,所以上面的查詢等於只有再找一號同學。
接下來我們簡單介紹另外一個叫做 FindOne()
的指令,基本上它就是Find 但是僅回傳查詢結果的第一個項目,但是要特別記得的是,因為 Collection 沒有順序可言,所以每次回傳的不一定是一個相同的值。對我來說,FindOne 只要是在更新或刪除資料時使用,我們之後會討論到。這裡的小觀念是, find 回傳的是一個 游標 (這就是為什麼如果使用的是 MongoSH,find有很多項目的值後他會說可以輸入 it
列出更多) 基本上就是一個可以疊代 (Iterate) 的指標,FindOne 是直接回傳一個文檔。這個觀念SQL中也有指示比較複雜所以在前面沒有討論到。
TL;DR SQL 中的 Select
db.grades.find(
{'scores.0.score': {$gte:99}},
{student_id:1, class_id:1, _id:0}
)
Projection,就是把結果投影出來,用 1 表示顯示 0 表示 不顯示。所以這邊就只顯示考試99分以上的學生跟課號。