節省數據用量的方法 |
|
|---|---|
| PUT | 將資料寫入或取代至定義的路徑,例如 fireblog/users/user1/<data> |
| PATCH | 更新已定義路徑的部分索引鍵,而不取代所有資料。 |
| POST | 將資料新增至 Firebase 資料庫的清單。每次傳送 POST 要求時,Firebase 用戶端都會產生不重複的鍵,例如 fireblog/users/<unique-id>/<data> |
| 刪除 | 從指定的 Firebase 資料庫參照中移除資料。 |
使用 PUT 寫入資料
透過 REST API 執行的基本寫入作業是 PUT。為了示範如何儲存資料,我們將建構一個包含貼文和使用者的網誌應用程式。應用程式的所有資料都會儲存在 `fireblog` 路徑下,Firebase 資料庫網址為 `https://docs-examples.firebaseio.com/fireblog`。
首先,將一些使用者資料儲存至 Firebase 資料庫。我們會為每位使用者儲存不重複的使用者名稱,以及全名和出生日期。由於每位使用者都有專屬的使用者名稱,因此我們已經有索引鍵,不需要建立索引鍵,所以在這裡使用 PUT 而不是 POST 是合理的。
使用 PUT,我們可以將字串、數字、布林值、陣列或任何 JSON 物件寫入 Firebase 資料庫。在本例中,我們會傳遞一個物件:
curl -X PUT -d '{
"alanisawesome": {
"name": "Alan Turing",
"birthday": "June 23, 1912"
}
}' 'https://docs-examples.firebaseio.com/fireblog/users.json'
JSON 物件儲存至資料庫時,物件屬性會自動以巢狀方式對應至子位置。如果前往新建立的節點,就會看到「Alan Turing」這個值。我們也可以直接將資料儲存至子位置:
curl -X PUT -d '"Alan Turing"' \ 'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome/name.json'
curl -X PUT -d '"June 23, 1912"' \ 'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome/birthday.json'
上述兩個範例 (同時寫入值和物件,以及分別寫入子位置) 會將相同的資料儲存至 Firebase 資料庫:
{
"users": {
"alanisawesome": {
"date_of_birth": "June 23, 1912",
"full_name": "Alan Turing"
}
}
}
如果要求成功,系統會傳回 200 OK HTTP 狀態碼,且回應會包含我們寫入資料庫的資料。第一個範例只會在監控資料的用戶端上觸發一個事件,而第二個範例則會觸發兩個事件。請注意,如果使用者路徑中已有資料,第一種方法會覆寫資料,但第二種方法只會修改每個獨立子節點的值,其他子節點則保持不變。PUT 相當於 JavaScript SDK 中的 set()。
使用 PATCH 更新資料
使用 PATCH 要求,我們可以在某個位置更新特定子項,而不會覆寫現有資料。接著,我們使用 PATCH 要求,將 Turing 的暱稱新增至他的使用者資料:
curl -X PATCH -d '{
"nickname": "Alan The Machine"
}' \
'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'
上述要求會將 nickname 寫入 alanisawesome 物件,但不會刪除 name 或 birthday 子項。請注意,如果我們在這裡發出 PUT 要求,name 和 birthday 就會遭到刪除,因為這些項目並未包含在要求中。Firebase 資料庫中的資料現在看起來像這樣:
{
"users": {
"alanisawesome": {
"date_of_birth": "June 23, 1912",
"full_name": "Alan Turing",
"nickname": "Alan The Machine"
}
}
}
如果要求成功,系統會傳回 200 OK HTTP 狀態碼,且回應會包含寫入資料庫的更新資料。
Firebase 也支援多路徑更新。這表示 PATCH 現在可以同時更新 Firebase 資料庫中多個位置的值,這項強大功能可協助您反正規化資料。使用多路徑更新,我們可以同時為 Alan 和 Grace 新增暱稱:
curl -X PATCH -d '{
"alanisawesome/nickname": "Alan The Machine",
"gracehopper/nickname": "Amazing Grace"
}' \
'https://docs-examples.firebaseio.com/fireblog/users.json'
更新後,Alan 和 Grace 的暱稱都會新增:
{
"users": {
"alanisawesome": {
"date_of_birth": "June 23, 1912",
"full_name": "Alan Turing",
"nickname": "Alan The Machine"
},
"gracehop": {
"date_of_birth": "December 9, 1906",
"full_name": "Grace Hopper",
"nickname": "Amazing Grace"
}
}
}請注意,如果嘗試透過寫入包含路徑的物件來更新物件,會導致不同的行為。如果改用以下方式更新 Grace 和 Alan,會發生什麼情況:
curl -X PATCH -d '{
"alanisawesome": {"nickname": "Alan The Machine"},
"gracehopper": {"nickname": "Amazing Grace"}
}' \
'https://docs-examples.firebaseio.com/fireblog/users.json'
這會導致不同的行為,也就是覆寫整個 /fireblog/users 節點:
{
"users": {
"alanisawesome": {
"nickname": "Alan The Machine"
},
"gracehop": {
"nickname": "Amazing Grace"
}
}
}使用條件式要求更新資料
您可以使用條件式要求 (相當於 REST 的交易),根據資料的現有狀態更新資料。舉例來說,如果您想增加贊成票計數器,並確保計數能準確反映多個同時贊成票,請使用條件式要求將新值寫入計數器。這樣一來,就不會發生兩次寫入作業將計數器變更為相同數字的情況,而是其中一個寫入要求失敗,您可以使用新值重試要求。- 如要在某個位置執行條件式要求,請取得該位置目前資料的專屬 ID 或 ETag。如果該位置的資料有所變更,ETag 也會隨之變更。您可以使用
PATCH以外的任何方法要求 ETag。以下範例使用GET要求。 具體來說,在標頭中呼叫 ETag 會在 HTTP 回應中傳回指定位置的 ETag。curl -i 'https://test.example.com/posts/12345/upvotes.json' -H 'X-Firebase-ETag: true'
HTTP/1.1 200 OK Content-Length: 6 Content-Type: application/json; charset=utf-8 Access-Control-Allow-Origin: * ETag: [ETAG_VALUE] Cache-Control: no-cache 10 // Current value of the data at the specified location
- 在下一個
PUT或DELETE要求中加入傳回的 ETag,更新與該 ETag 值相符的資料。延續上述範例,如要將計數器更新為 11 (比初始擷取值 10 大 1),並在值不相符時失敗,請使用下列程式碼: 如果指定位置的資料值仍為 10,curl -iX PUT -d '11' 'https://[PROJECT_ID].firebaseio.com/posts/12345/upvotes.json' -H 'if-match:[ETAG_VALUE]'
PUT要求中的 ETag 就會相符,要求也會成功,並將 11 寫入資料庫。 如果位置與 ETag 不再相符 (例如其他使用者將新值寫入資料庫),要求就會失敗,不會寫入該位置。傳回的回應包含新值和 ETag。HTTP/1.1 200 OK Content-Length: 6 Content-Type: application/json; charset=utf-8 Access-Control-Allow-Origin: * Cache-Control: no-cache 11 // New value of the data at the specified location, written by the conditional request
HTTP/1.1 412 Precondition Failed Content-Length: 6 Content-Type: application/json; charset=utf-8 Access-Control-Allow-Origin: * ETag: [ETAG_VALUE] Cache-Control: no-cache 12 // New value of the data at the specified location
- 如果決定重試要求,請使用新資訊。Realtime Database 不會自動重試失敗的條件式要求。不過,您可以使用新值和 ETag,根據失敗回應傳回的資訊建立新的條件式要求。
REST 條件式要求會實作 HTTP if-match 標準。不過,這類廣告與標準廣告有以下差異:
- 每個 if-match 要求只能提供一個 ETag 值,不能提供多個。
- 雖然標準建議所有要求都應傳回 ETag,但即時資料庫只會傳回包含
X-Firebase-ETag標頭的要求。這可降低標準要求的已計費用。
條件式要求也可能比一般 REST 要求慢。
儲存資料清單
如要為新增至 Firebase 資料庫參照的每個子項產生以時間戳記為基礎的不重複索引鍵,我們可以傳送 POST 要求。對於 users 路徑,由於每位使用者都有專屬的使用者名稱,因此定義自己的索引鍵是合理的做法。不過,當使用者在應用程式中新增網誌文章時,我們會使用 POST 要求,為每篇網誌文章自動產生索引鍵:
curl -X POST -d '{
"author": "alanisawesome",
"title": "The Turing Machine"
}' 'https://docs-examples.firebaseio.com/fireblog/posts.json'
posts 路徑現在包含下列資料:
{
"posts": {
"-JSOpn9ZC54A4P4RoqVa": {
"author": "alanisawesome",
"title": "The Turing Machine"
}
}
}
請注意,由於我們使用了 POST 要求,因此系統會自動為我們產生 -JSOpn9ZC54A4P4RoqVa 鍵。如果要求成功,系統會傳回 200 OK HTTP 狀態碼,且回應會包含新增資料的索引鍵:
{"name":"-JSOpn9ZC54A4P4RoqVa"}移除資料
如要從資料庫中移除資料,我們可以傳送 DELETE 要求,並附上要刪除資料的路徑網址。下列指令會從 users 路徑中刪除 Alan:
curl -X DELETE \ 'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'
如果 DELETE 要求成功,系統會傳回 200 OK HTTP 狀態碼,以及包含 JSON null 的回應。
URI 參數
將資料寫入資料庫時,REST API 接受下列 URI 參數:
授權
auth 要求參數可讓您存取受 Firebase Realtime Database Security Rules 保護的資料,且所有要求類型都支援此參數。引數可以是 Firebase 應用程式密鑰或驗證權杖,我們會在使用者授權一節中說明。在以下範例中,我們傳送了含有 auth 參數的 POST 要求,其中 CREDENTIAL 是 Firebase 應用程式密鑰或驗證權杖:
curl -X POST -d '{"Authenticated POST request"}' \
'https://docs-examples.firebaseio.com/auth-example.json?auth=CREDENTIAL'
列印
print 參數可讓我們指定資料庫回應的格式。在要求中加入 print=pretty,系統就會以人類可讀的格式傳回資料。GET、PUT、POST、PATCH 和 DELETE 要求支援 print=pretty。
如要在寫入資料時抑制伺服器的輸出內容,可以在要求中加入 print=silent。如果要求成功,產生的回應會是空白,並以 204 No Content HTTP 狀態碼表示。GET、PUT、POST 和 PATCH 要求支援 print=silent。
寫入伺服器值
伺服器值可以使用預留位置值寫入某個位置,預留位置值是具有單一 ".sv" 鍵的物件。該鍵的值是我們要設定的伺服器值類型。舉例來說,如要在建立使用者時設定時間戳記,可以執行下列操作:
curl -X PUT -d '{".sv": "timestamp"}' \
'https://docs-examples.firebaseio.com/alanisawesome/createdAt.json'
"timestamp" 是唯一支援的伺服器值,代表自 UNIX 紀元起算的時間 (以毫秒為單位)。
提升寫入效能
如果我們要將大量資料寫入資料庫,可以使用 print=silent 參數來提升寫入效能並減少頻寬用量。在正常寫入行為中,伺服器會回應寫入的 JSON 資料。
如果指定 print=silent,伺服器會在收到資料後立即關閉連線,減少頻寬用量。
如果我們向資料庫發出多項要求,可以在 HTTP 標頭中傳送 Keep-Alive 要求,重複使用 HTTPS 連線。
錯誤狀況
在下列情況下,REST API 會傳回錯誤代碼:
| HTTP 狀態碼 | |
|---|---|
| 400 Bad Request |
下列其中一項錯誤條件:
|
| 401 未授權 |
下列其中一項錯誤條件:
|
| 404 找不到網頁 | 找不到指定的 Firebase 資料庫。 |
| 500 內部伺服器錯誤 | 伺服器傳回錯誤。詳情請參閱錯誤訊息。 |
| 503 Service Unavailable | 指定的 Firebase 即時資料庫暫時無法使用,因此系統未嘗試執行要求。 |
保護資料
Firebase 具有安全性語言,可讓我們定義哪些使用者有權讀取及寫入資料的不同節點。詳情請參閱 Realtime Database Security Rules。
我們已介紹如何儲存資料,下一節將說明如何透過 REST API 從 Firebase 資料庫擷取資料。