iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 14
2
AI & Data

與資料庫共舞系列 第 14

Day 14 — 今晚我想來點 MongoDB 的資料

  • 分享至 

  • xImage
  •  

拿到有資料的資料庫,一件事情就是要來做資料查詢! 因為現在在MongoDB裡面的資料,都存放在同一個文件 (Document) 中,所以相對於之前我們在寫SQL的時候需要去考量關聯表,現在的查詢就沒有那麼複雜啦 。但是為讓人比較頭痛的事情是 MongoDB 使用大量的大括號,在撰寫的時候務必特別小心括號有沒有對齊,就讓我們開始從最簡單的尋找文檔開始寫吧。

Find 與 Limit

在昨天的文章最後,我們使用了 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 放入查詢的過濾條件

https://ithelp.ithome.com.tw/upload/images/20200914/20129829k1f6yiyqRx.png

讓我們依照class_id 排序,這裡的 1 表示有小到大排序,如果要反過來可以使用 -1 .

db.grades.find({student_id:2}).sort({class_id:1})

https://ithelp.ithome.com.tw/upload/images/20200914/20129829vaz629cWYX.png

到這邊我就假設讀者已經發現 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

接下來我們簡單介紹另外一個叫做 FindOne() 的指令,基本上它就是Find 但是僅回傳查詢結果的第一個項目,但是要特別記得的是,因為 Collection 沒有順序可言,所以每次回傳的不一定是一個相同的值。對我來說,FindOne 只要是在更新或刪除資料時使用,我們之後會討論到。這裡的小觀念是, find 回傳的是一個 游標 (這就是為什麼如果使用的是 MongoSH,find有很多項目的值後他會說可以輸入 it 列出更多) 基本上就是一個可以疊代 (Iterate) 的指標,FindOne 是直接回傳一個文檔。這個觀念SQL中也有指示比較複雜所以在前面沒有討論到。

投影 Projection

TL;DR SQL 中的 Select

db.grades.find(
	{'scores.0.score': {$gte:99}}, 
	{student_id:1, class_id:1, _id:0}
)

https://ithelp.ithome.com.tw/upload/images/20200914/2012982928zeVVjMXN.png

Projection,就是把結果投影出來,用 1 表示顯示 0 表示 不顯示。所以這邊就只顯示考試99分以上的學生跟課號。


上一篇
Day13 — 架起MongoDB囉!
下一篇
Day 15 — 一步一步寫出複雜的 MongoDB 指令
系列文
與資料庫共舞30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言