Cách lưu dữ liệu |
|
|---|---|
| ĐẶT | Ghi hoặc thay thế dữ liệu vào đường dẫn đã xác định, chẳng hạn như fireblog/users/user1/<data> |
| SỬA | Cập nhật một số khoá cho đường dẫn đã xác định mà không thay thế tất cả dữ liệu. |
| POST | Thêm vào danh sách dữ liệu trong cơ sở dữ liệu Firebase. Mỗi khi chúng tôi gửi yêu cầu POST, ứng dụng Firebase sẽ tạo một khoá duy nhất, chẳng hạn như fireblog/users/<unique-id>/<data> |
| XÓA | Xoá dữ liệu khỏi tham chiếu cơ sở dữ liệu Firebase đã chỉ định. |
Ghi dữ liệu bằng PUT
Thao tác ghi cơ bản thông qua REST API là PUT. Để
minh hoạ việc lưu dữ liệu, chúng ta sẽ xây dựng một ứng dụng blog có bài đăng và người dùng. Tất cả dữ liệu cho ứng dụng của chúng ta sẽ được lưu trữ trong đường dẫn `fireblog`, tại URL cơ sở dữ liệu Firebase `https://docs-examples.firebaseio.com/fireblog`.
Hãy bắt đầu bằng cách lưu một số dữ liệu người dùng vào cơ sở dữ liệu Firebase. Chúng ta sẽ lưu trữ từng người dùng theo một tên người dùng duy nhất, đồng thời lưu trữ tên đầy đủ và ngày sinh của họ. Vì mỗi người dùng sẽ có một
tên người dùng duy nhất, nên bạn nên sử dụng PUT thay vì POST vì
chúng ta đã có khoá và không cần tạo khoá.
Khi sử dụng PUT, chúng ta có thể ghi chuỗi, số, boolean, mảng hoặc bất kỳ đối tượng JSON nào vào
cơ sở dữ liệu Firebase. Trong trường hợp này, chúng ta sẽ chuyển đối tượng đó:
curl -X PUT -d '{
"alanisawesome": {
"name": "Alan Turing",
"birthday": "June 23, 1912"
}
}' 'https://docs-examples.firebaseio.com/fireblog/users.json'
Khi một đối tượng JSON được lưu vào cơ sở dữ liệu, các thuộc tính của đối tượng sẽ tự động được liên kết với các vị trí con theo kiểu lồng nhau. Nếu chuyển đến nút mới tạo, chúng ta sẽ thấy giá trị "Alan Turing". Chúng ta cũng có thể lưu dữ liệu trực tiếp vào vị trí con:
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'
Hai ví dụ ở trên (ghi giá trị cùng lúc với đối tượng và ghi riêng vào các vị trí con) sẽ dẫn đến việc lưu cùng một dữ liệu vào cơ sở dữ liệu Firebase:
{
"users": {
"alanisawesome": {
"date_of_birth": "June 23, 1912",
"full_name": "Alan Turing"
}
}
}
Yêu cầu thành công sẽ được biểu thị bằng mã trạng thái HTTP 200 OK và phản hồi sẽ chứa dữ liệu mà chúng ta đã ghi vào cơ sở dữ liệu. Ví dụ đầu tiên sẽ chỉ
kích hoạt một sự kiện trên các ứng dụng đang theo dõi dữ liệu, trong khi ví dụ thứ hai sẽ kích hoạt
hai sự kiện. Điều quan trọng cần lưu ý là nếu dữ liệu đã tồn tại ở đường dẫn người dùng, thì phương pháp đầu tiên
sẽ ghi đè dữ liệu đó, nhưng phương thức thứ hai sẽ chỉ sửa đổi giá trị của từng nút con riêng biệt
trong khi giữ nguyên các nút con khác. PUT tương đương với
set() trong SDK JavaScript.
Cập nhật dữ liệu bằng PATCH
Khi sử dụng yêu cầu PATCH, chúng ta có thể cập nhật các nút con cụ thể tại một vị trí mà không
ghi đè dữ liệu hiện có. Hãy thêm biệt danh của Turing vào dữ liệu người dùng của anh ấy bằng yêu cầu PATCH:
curl -X PATCH -d '{
"nickname": "Alan The Machine"
}' \
'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'
Yêu cầu ở trên sẽ ghi nickname vào đối tượng alanisawesome
mà không xoá các nút con name hoặc birthday. Xin lưu ý rằng nếu chúng ta đã
đưa ra yêu cầu PUT ở đây, thì name và birthday
sẽ bị xoá vì chúng không được đưa vào yêu cầu. Dữ liệu trong cơ sở dữ liệu Firebase
của chúng ta hiện trông như sau:
{
"users": {
"alanisawesome": {
"date_of_birth": "June 23, 1912",
"full_name": "Alan Turing",
"nickname": "Alan The Machine"
}
}
}
Yêu cầu thành công sẽ được biểu thị bằng mã trạng thái HTTP 200 OK và phản hồi sẽ chứa dữ liệu đã cập nhật được ghi vào cơ sở dữ liệu.
Firebase cũng hỗ trợ cập nhật nhiều đường dẫn. Điều này có nghĩa là PATCH hiện có thể cập nhật các giá trị tại nhiều vị trí trong cơ sở dữ liệu Firebase cùng một lúc. Đây là một tính năng mạnh mẽ giúp bạn
chuẩn hoá dữ liệu. Khi sử dụng tính năng cập nhật nhiều đường dẫn, chúng ta có thể thêm biệt danh cho cả Alan và Grace cùng một lúc:
curl -X PATCH -d '{
"alanisawesome/nickname": "Alan The Machine",
"gracehopper/nickname": "Amazing Grace"
}' \
'https://docs-examples.firebaseio.com/fireblog/users.json'
Sau khi cập nhật này, cả Alan và Grace đều đã được thêm biệt danh:
{
"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"
}
}
}Xin lưu ý rằng việc cố gắng cập nhật các đối tượng bằng cách ghi các đối tượng có đường dẫn đi kèm sẽ dẫn đến hành vi khác. Hãy xem điều gì sẽ xảy ra nếu chúng ta cố gắng cập nhật Grace và Alan theo cách này:
curl -X PATCH -d '{
"alanisawesome": {"nickname": "Alan The Machine"},
"gracehopper": {"nickname": "Amazing Grace"}
}' \
'https://docs-examples.firebaseio.com/fireblog/users.json'
Điều này dẫn đến hành vi khác, cụ thể là ghi đè toàn bộ nút /fireblog/users:
{
"users": {
"alanisawesome": {
"nickname": "Alan The Machine"
},
"gracehop": {
"nickname": "Amazing Grace"
}
}
}Cập nhật dữ liệu bằng yêu cầu có điều kiện
Bạn có thể sử dụng các yêu cầu có điều kiện (tương đương với giao dịch REST) để cập nhật dữ liệu theo trạng thái hiện có của dữ liệu đó. Ví dụ: nếu bạn muốn tăng bộ đếm lượt thích và muốn đảm bảo số lượt thích phản ánh chính xác nhiều lượt thích đồng thời, hãy sử dụng yêu cầu có điều kiện để ghi giá trị mới vào bộ đếm. Thay vì hai lần ghi làm thay đổi bộ đếm thành cùng một số, một trong các yêu cầu ghi sẽ không thành công và sau đó bạn có thể thử lại yêu cầu với giá trị mới.- Để thực hiện yêu cầu có điều kiện tại một vị trí, hãy lấy giá trị nhận dạng duy nhất
cho dữ liệu hiện tại tại vị trí đó hoặc ETag. Nếu dữ liệu thay đổi tại
vị trí đó, ETag cũng sẽ thay đổi. Bạn có thể yêu cầu ETag bằng mọi
phương thức khác ngoài
PATCH. Ví dụ sau đây sử dụng yêu cầuGET. Cụ thể là việc gọi ETag trong tiêu đề sẽ trả về ETag của vị trí đã chỉ định trong phản hồi HTTP.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
- Đưa ETag đã trả về vào yêu cầu
PUThoặcDELETEtiếp theo để cập nhật dữ liệu khớp chính xác với giá trị ETag đó. Theo ví dụ của chúng ta, để cập nhật bộ đếm thành 11 (tức là lớn hơn 1 so với giá trị ban đầu đã tìm nạp là 10) và không thực hiện được yêu cầu nếu giá trị không còn khớp, hãy sử dụng mã sau: Nếu giá trị của dữ liệu tại vị trí đã chỉ định vẫn là 10, thì ETag trong yêu cầucurl -iX PUT -d '11' 'https://[PROJECT_ID].firebaseio.com/posts/12345/upvotes.json' -H 'if-match:[ETAG_VALUE]'
PUTsẽ khớp và yêu cầu thành công, ghi 11 vào cơ sở dữ liệu. Nếu vị trí không còn khớp với ETag (điều này có thể xảy ra nếu người dùng khác ghi giá trị mới vào cơ sở dữ liệu), thì yêu cầu sẽ không thành công mà không ghi vào vị trí. Phản hồi trả về bao gồm giá trị và ETag mới.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
- Hãy sử dụng thông tin mới nếu bạn quyết định thử lại yêu cầu. Realtime Database không tự động thử lại các yêu cầu có điều kiện không thành công. Tuy nhiên, bạn có thể sử dụng giá trị và ETag mới để tạo yêu cầu có điều kiện mới bằng thông tin do phản hồi không thành công trả về.
Các yêu cầu có điều kiện dựa trên REST triển khai tiêu chuẩn HTTP if-match. Tuy nhiên, chúng khác với tiêu chuẩn theo những cách sau:
- Bạn chỉ có thể cung cấp một giá trị ETag cho mỗi yêu cầu if-match, không phải nhiều giá trị.
- Mặc dù tiêu chuẩn đề xuất rằng ETag sẽ được trả về cùng với tất cả yêu cầu,
Cơ sở dữ liệu thời gian thực chỉ trả về ETag cùng với các yêu cầu bao gồm
X-Firebase-ETagtiêu đề. Điều này giúp giảm chi phí thanh toán cho các yêu cầu tiêu chuẩn.
Các yêu cầu có điều kiện cũng có thể chậm hơn các yêu cầu REST thông thường.
Lưu danh sách dữ liệu
Để tạo khoá duy nhất dựa trên dấu thời gian cho mọi nút con được thêm vào tham chiếu cơ sở dữ liệu Firebase
chúng ta có thể gửi yêu cầu POST. Đối với đường dẫn users, bạn nên
xác định khoá riêng vì mỗi người dùng có một tên người dùng duy nhất. Nhưng khi người dùng thêm bài đăng trên blog vào
ứng dụng, chúng ta sẽ sử dụng yêu cầu POST để tự động tạo khoá cho mỗi bài đăng trên blog:
curl -X POST -d '{
"author": "alanisawesome",
"title": "The Turing Machine"
}' 'https://docs-examples.firebaseio.com/fireblog/posts.json'
Đường dẫn posts của chúng ta hiện có dữ liệu sau:
{
"posts": {
"-JSOpn9ZC54A4P4RoqVa": {
"author": "alanisawesome",
"title": "The Turing Machine"
}
}
}
Xin lưu ý rằng khoá -JSOpn9ZC54A4P4RoqVa đã được tự động tạo cho chúng ta vì
chúng ta đã sử dụng yêu cầu POST Yêu cầu thành công sẽ được biểu thị bằng mã trạng thái HTTP 200 OK
và phản hồi sẽ chứa khoá của dữ liệu mới được thêm:
{"name":"-JSOpn9ZC54A4P4RoqVa"}Xoá dữ liệu
Để xoá dữ liệu khỏi cơ sở dữ liệu, chúng ta có thể gửi yêu cầu DELETE bằng
URL của đường dẫn mà chúng ta muốn xoá dữ liệu. Thao tác sau sẽ xoá Alan khỏi đường dẫn
users
curl -X DELETE \ 'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'
Yêu cầu DELETE thành công sẽ được biểu thị bằng mã trạng thái HTTP 200 OK với phản hồi chứa JSON null.
Tham số URI
REST API chấp nhận các tham số URI sau đây khi ghi dữ liệu vào cơ sở dữ liệu:
uỷ quyền
Tham số yêu cầu auth cho phép truy cập vào dữ liệu được bảo vệ bởi
Firebase Realtime Database Security Rules và được
tất cả các loại yêu cầu hỗ trợ. Đối số có thể là bí mật ứng dụng Firebase hoặc một
mã thông báo xác thực. Chúng ta sẽ đề cập đến vấn đề này trong phần uỷ quyền người dùng. Trong ví dụ sau, chúng ta sẽ gửi yêu cầu POST với tham số
auth, trong đó CREDENTIAL là bí mật ứng dụng Firebase hoặc
mã thông báo xác thực:
curl -X POST -d '{"Authenticated POST request"}' \
'https://docs-examples.firebaseio.com/auth-example.json?auth=CREDENTIAL'
in
Tham số print cho phép chúng ta chỉ định định dạng của phản hồi từ cơ sở dữ liệu. Việc thêm print=pretty vào yêu cầu sẽ trả về dữ liệu ở định dạng mà con người có thể đọc được. print=pretty được các yêu cầu GET,
PUT, POST, PATCH, và DELETE hỗ trợ.
Để ngăn máy chủ xuất dữ liệu khi ghi dữ liệu, chúng ta có thể thêm
print=silent vào yêu cầu. Phản hồi kết quả sẽ trống và được biểu thị bằng
mã trạng thái HTTP 204 No Content nếu yêu cầu thành công.
print=silent được các yêu cầu GET, PUT,
POST, và PATCH hỗ trợ.
Ghi giá trị máy chủ
Bạn có thể ghi các giá trị máy chủ tại một vị trí bằng cách sử dụng giá trị giữ chỗ. Đây là đối tượng có một
khoá ".sv". Giá trị cho khoá đó là loại giá trị máy chủ mà chúng ta muốn đặt.
Ví dụ: để đặt dấu thời gian khi người dùng được tạo, chúng ta có thể làm như sau:
curl -X PUT -d '{".sv": "timestamp"}' \
'https://docs-examples.firebaseio.com/alanisawesome/createdAt.json'
"timestamp" là giá trị máy chủ duy nhất được hỗ trợ và là thời gian kể từ thời điểm bắt đầu thời gian UNIX
tính bằng mili giây.
Cải thiện hiệu suất ghi
Nếu đang ghi lượng lớn dữ liệu vào cơ sở dữ liệu, chúng ta có thể sử dụng tham số
print=silent để cải thiện hiệu suất ghi và giảm mức sử dụng băng thông. Trong hành vi ghi thông thường, máy chủ sẽ phản hồi bằng dữ liệu JSON đã được ghi.
Khi print=silent được chỉ định, máy chủ sẽ đóng ngay kết nối sau khi nhận được dữ liệu, giúp giảm mức sử dụng băng thông.
Trong trường hợp chúng ta thực hiện nhiều yêu cầu đối với cơ sở dữ liệu, chúng ta có thể sử dụng lại kết nối HTTPS
bằng cách gửi yêu cầu Keep-Alive trong tiêu đề HTTP.
Điều kiện lỗi
REST API sẽ trả về mã lỗi trong các trường hợp sau:
| Mã trạng thái HTTP | |
|---|---|
| 400 Yêu cầu không hợp lệ |
Một trong các điều kiện lỗi sau:
|
| 401 Không được phép |
Một trong các điều kiện lỗi sau:
|
| 404 Không tìm thấy | Không tìm thấy cơ sở dữ liệu Firebase đã chỉ định. |
| 500 Lỗi máy chủ nội bộ | Máy chủ trả về lỗi. Hãy xem thông báo lỗi để biết thêm thông tin chi tiết. |
| 503 Dịch vụ không hoạt động | Cơ sở dữ liệu thời gian thực Firebase đã chỉ định tạm thời không hoạt động, nghĩa là yêu cầu không được thực hiện. |
Bảo mật dữ liệu
Firebase có ngôn ngữ bảo mật cho phép chúng ta xác định những người dùng có quyền đọc và ghi vào các nút khác nhau của dữ liệu. Bạn có thể đọc thêm về vấn đề này trong Realtime Database Security Rules.
Bây giờ chúng ta đã đề cập đến việc lưu dữ liệu, bạn có thể tìm hiểu cách truy xuất dữ liệu từ cơ sở dữ liệu Firebase thông qua REST API trong phần tiếp theo.