Firebase初探(2)-基礎用法與排序
上一篇我們說到Firebase的安裝與啟用,這裏接著說明Firebase的基礎用法與資料的排序方式。本篇使用的是Firebase的Realtime Database。
基礎用法
Firebase的用法中,常用的有下面幾項:
- ref 路徑
- set 新增
- once, on 讀取資料
- push 新增資料,與set不同點
- child子路徑
- remove移除
排序方式
Firebase的資料排序方式中,下面幾個方法比較常用到。
- orderByChild 排序的操作。
- startAt, endAt, equalTo 等與過濾條件有關之操作。
- limitToFirst, limitToLast 等與限制筆數有關之操作。
我們就對這些部分分別進行說明。
ref()與set()
假設大家已經連接了資料庫(可以參考上一篇),現在就來測試看看,該如何操控資料庫。為了這個目的,我們需要暸解下面的指令:
ref() : 尋找資料庫路徑(預設:根目錄)
這個指令可以尋找資料庫的路徑位置。其預設值為根目錄,因此如果在 ref()括弧中間保留空白的話(如下),表示從根目錄開始。
db.ref()
set(): 新增資料(寫入方式:覆蓋)
在基礎的操作中,使用set可以將資料庫中原來存在的值全部取代掉,換上目前指定的內容。因此,可以說非常具有破壞性。
繼續上一篇的程式碼,我們可以使用set()來新增資料到資料庫中。例如:我們想要加入『Hi』到資料庫中。
db.ref().set('Hi')
發佈看看:結果出現錯誤訊息。
因為資料庫的權限不夠。我們可以回到firebase的介面看看。在規則的地方,我們發現讀取的權限與寫入的權限都是「false」。這表示我們無法讀寫這個資料庫。
為了測試一下資料庫的讀寫,我們「暫時」將權限改成true。之所以是「暫時」,是因為這樣子門戶洞開狀態在實務上是很危險的,在此只為了方便說明的便宜措施。
在重新整理index.html測試一下這次是否可以寫入資料庫?
成功了,資料庫中出現「Hi」。
Firebase可以儲存物件
在set()裡面除了放字串外,也可以存入物件。存入物件的方式如下。大家應該都知道,物件的格式為「鍵、值」格式。假設我們要存入一個「鍵」為home而「值」為Taiwan資料,方法如下:
key為home
value為Taiwan
db.ref().set({ "home": 'Taiwan'})
資料庫儲存的結果:
如果有兩個會員的資料想要存入,我們可以先設定資料為物件data。細節如下:
var data = null; data = { user1: { name: 'Jonny', num: 1 }, user2: { name: 'Mary', num: 2 }}
將上面的資料存入firebase裡面。
db.ref().set(data)
資料庫儲存的結果:
如果想要將第一個使用者的名稱改為Tom,可以用下面的方式:
firebase.database().ref('user1/name').set('Tom')
資料庫儲存的結果:
要注意的是, set() 在每次寫入的時後,會覆蓋掉目前資料庫該位置的內容,所以要注意ref() 是否有指定到正確的位置,不然有可能會發生慘劇。
Firebase不可以儲存陣列格式
下面的式子可以執行嗎?我們想要儲存一組陣列到資料庫中。
firebase.database().ref().set([1,2,3,4,5])
資料庫儲存的結果:
可以存入資料庫,但是存入的資料並不是陣列格式,而是物件格式。所以,在設計資料庫的時候,要以物件方式來思考才行。
設計多層次的資料結構
假設我們賣兩項產品(products):筆(pen)與筆記本(note)。這兩項產品各有各的價格以及它的存貨量。
產品:
訂單:
資料結構可以設計如下:
var data = null;data = { products: { pen: { price: 15, num: 10 }, note: { price: 30, num: 20 } }, orders: { 1: { pen: 2 }, 2: { pen: 5, note: 2 } }}
存入資料庫:
db.ref().set(data)
資料庫儲存的結果:
once讀取資料
使用once可以讀取一次資料庫的資料。假設目前資料庫的結構如下圖所示,我們要使用once來讀取他,並且顯示在console中:
首先,指定一個變數myData,讓這個變數對應到資料庫myData的路徑。
var myData = firebase.database().ref('myData');
接著就可以使用once來讀取它。我們使用myData.once(a,b)的方式來讀取。
myData.once(a,b)
其中a為value而b為一個無名函數。這個無名函數中需要一個參數,我們一般習慣將這個參數取名為snapshot。
因為使用once讀取的行為,就像是拿一個相機對著資料庫照一張快照一樣,把那一霎那的狀況忠實的顯示出來。
我們可以用snapshot.val()取出快照的內容。由於是非同步事件,想要對取得的資料進行後續操作時,要寫在 callback function 中。
myData.once('value', function(snapshot){var data = snapshot.val()console.log(data)})
因此,顯示在console中的結果如下:
on讀取資料
使用on可以即時監聽並且讀取資料庫的資料,其他在用法上和 once 幾乎一樣。
如下程式碼,只是把once改成on,就產生不一樣的效果。
myData.on('value', function(snapshot){var data = snapshot.val()console.log(data)})
使用on的話,程式會在背景待命,一旦資料變動的時候,就會重新印出新的結果。由於這種特性,on常常被用在需要即時更新訊息的聊天室應用程式的開發上。
child子路徑
我們可以用child找到子路徑。
// 1.
var todos = db.ref('todos');
例如使用上面1這樣的撰寫方式與下面2的方式是一樣的。
// 2.
var todos = db.ref().child('todos');
使用下面2的程式碼,會事先指向到根目錄(ref()
),再從根目錄移到子路徑todos(child('todos')
)與上面1的程式碼,直接指向todo路徑(ref('todos')
)是一樣的。
新增資料
新增資料進入Realtime Database有幾個方式:
- set
- push
- update
這三種的用法大致上都一樣,但是要注意的是三者間的不同。
set 會直接取代當前路徑中的所有資料,而update 只修改相關資料,不會直接取代路徑中的所有資料,對於只需要修改局部資料來說,這個方式比較適合。
如果要修改的資料在資料庫中找不到該路徑的話,update就會自動新增一筆資料。
至於push ,一樣是新增資料,但它既不會取代也不會更新任何資料,並且會自己帶入一個隨機產生的 key。
push可以增加一個物件進資料庫。下面我們用這段程式碼示範一下:
var db = firebase.database()var todos = db.ref('todos');todos.push({content:'買菜'});
結果,資料庫增加了一個物件,並且產生了一組隨機的key值。
todos.push({content:'逛街'});
再寫一次,就會再加上一筆。你可以發現,原來的資料還在。
刪除資料
如果想要刪除資料,該如何做?在Firebase中要刪除資料可以使用remove來處理。
繼續上面的例子,我們執行remove()的時候,就可以刪除該筆資料。
todos.child('-M3QA3JL55SqRpzd3AuF').remove()
排序方式
如果您曾經學過SQL指令的話,應該對於order by之類的語法不陌生吧。在資料庫的存取與控制上,這類的這類的指令十分常見。那麼在Firebase中是否也有相似的操作方式?
orderBy排序
是的,在Firebase中我們可以看到orderBy這個方法的使用。如字面意思,orderBy是用來排序的。
在Firebase Realtime Database中,你可以透過「Key」、「Value」或者是「Child的值」來獲取資料。也可以對資料庫進行篩選。因此orderBy還可以分成:
要注意個是,你一次只能用『一個』orderBy來排序。如果不慎在同ㄧ個擷取時用上兩個以上的orderBy會導致錯誤發生。
orderByChild 排序
orderByChild()依據資料某一個特定子節點來做排序,產生新的結果。orderByChild()不可以配重複使用,否則會導致錯誤發生。
範例:假設我們有下面的資料。
範例程式碼:
var db = firebase.database()var userRef = db.ref('user');userRef.orderByChild('weight').once('value',function(snapshot){ snapshot.forEach(function(item){ console.log(item.val()); }) console.log(snapshot.val());})
結果:
第一個console顯示的結果是透過orderByChild排序後的資料,我們針對weight值來進行排序。
第二個console顯示的結果是沒有透過排序的資料,你可以清楚地發現順序上的差異。
orderByKey 排序
orderByKey()中不需要帶參數,依據資料的Key來做排序,產生新的結果。排序的方式依照資料Key的升冪來排序,也就是資料少的排前面資料大的排後面。
orderByValue 排序
orderByValue中不需要帶參數,依據資料的value來做排序,產生新的結果。如果查詢的子級屬於字串、數字或布林值,則可以按其升冪值進行排序。
過濾條件
區間限制
startAt:大於
比如說我們想要過濾掉,體重70公斤以下的人,可以使用startAt(70)。
userRef.orderByChild("weight").startAt(70).once("value", function (snapshot) { snapshot.forEach(function (item) { console.log(item.val()); });});
結果顯示大於70公斤的會員。
endAt:小於
比如說我們想要過濾掉,體重50公斤以上的人,可以使用startAt(50)。
userRef.orderByChild("weight").endAt(50).once("value", function (snapshot) { snapshot.forEach(function (item) { console.log(item.val()); });});
結果顯示:裡面包含50公斤者。
equalTo:等於
比如說我們想要體重等於50公斤的人時,就要使用equalTo(50)。
userRef.orderByChild("weight").equalTo(50).once("value", function (snapshot) { snapshot.forEach(function (item) { console.log(item.val()); });});
結果只顯示體重為50公斤者。
如果你想要知道是誰的話,可以加上key (item.key)
userRef.orderByChild("weight").equalTo(50).once("value", function (snapshot) { snapshot.forEach(function (item) { console.log(item.val(), item.key); });});
結果會顯示這筆被篩選出資料的key值。
筆數限制
如果資料庫的資料很多,而我們只需要其中的一部分資料的話,該如何處理?
userRef.orderByChild("weight").startAt(70).once("value", function (snapshot) { snapshot.forEach(function (item) { console.log(item.val()); });});
limitToFirst從頭開始的前幾筆
如前例體重70大於公斤的會員,如果我只需要其中第一筆資料的話,該如何處理?
userRef.orderByChild("weight").startAt(70).limitToFirst(1).once("value", function (snapshot) { snapshot.forEach(function (item) { console.log(item.val()); });});
可以使用 .limitToFirst(1),找到第一筆資料。
limitToLast 從最尾端起算的幾筆
想要最後一筆資料,可以使用.limitToLast(1),如果是最後5筆資料,可以使用.limitToLast(5)。
相關文章:Firebase初探(1)- 安裝與設定