Truy xuất dữ liệu

Đọc dữ liệu bằng phương thức GET

Chúng ta có thể đọc dữ liệu từ cơ sở dữ liệu Firebase bằng cách đưa ra yêu cầu GET cho điểm cuối URL của cơ sở dữ liệu đó. Hãy tiếp tục với ví dụ về blog trong phần trước và đọc tất cả dữ liệu bài đăng trên blog của chúng ta:

curl 'https://docs-examples.firebaseio.com/fireblog/posts.json?print=pretty'

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 đang truy xuất.

Thêm tham số URI

REST API chấp nhận một số tham số truy vấn khi đọc dữ liệu từ cơ sở dữ liệu Firebase của chúng tôi. Dưới đây là danh sách các thông số thường dùng nhất. Để xem danh sách đầy đủ, hãy tham khảo Tài liệu tham khảo về REST API.

auth

Tham số yêu cầu auth cho phép truy cập vào dữ liệu được bảo vệ bằng 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à khoá bí mật của ứng dụng Firebase hoặc mã thông báo xác thực, như mô tả trong phần Người dùng trong dự án Firebase. Trong ví dụ sau, chúng ta sẽ gửi một yêu cầu GET có tham số auth, trong đó CREDENTIAL là khoá bí mật của ứng dụng Firebase hoặc mã thông báo xác thực:

curl 'https://docs-examples.firebaseio.com/auth-example.json?auth=CREDENTIAL'

in

Việc chỉ định print=pretty sẽ trả về dữ liệu ở định dạng dễ đọc.

curl 'https://docs-examples.firebaseio.com/fireblog/posts.json?print=pretty'

Việc chỉ định print=silent sẽ trả về 204 No Content khi thành công.

curl 'https://docs-examples.firebaseio.com/fireblog/posts.json?print=silent'

callback

Để thực hiện các lệnh gọi REST từ một trình duyệt web trên các miền, bạn có thể sử dụng JSONP để bao bọc phản hồi trong một hàm gọi lại JavaScript. Thêm callback= để REST API bao bọc dữ liệu được trả về trong hàm gọi lại mà bạn chỉ định. Ví dụ:

<script>
  function gotData(data) {
    console.log(data);
  }
</script>
<script src="https://docs-examples.firebaseio.com/fireblog/posts.json?callback=gotData">

nông

Đây là một tính năng nâng cao, được thiết kế để giúp bạn làm việc với các tập dữ liệu lớn mà không cần tải mọi thứ xuống. Để sử dụng, hãy thêm shallow=true làm tham số. Thao tác này sẽ giới hạn độ sâu của dữ liệu được trả về. Nếu dữ liệu tại vị trí đó là một nguyên hàm JSON (chuỗi, số hoặc boolean), thì giá trị của dữ liệu sẽ được trả về. Nếu ảnh chụp nhanh dữ liệu tại vị trí là một đối tượng JSON, thì các giá trị cho mỗi khoá sẽ bị cắt ngắn thành true. Ví dụ: sử dụng dữ liệu bên dưới:

{
  "message": {
    "user": {
      "name": "Chris"
    },
    "body": "Hello!"
  }
}

// A request to /message.json?shallow=true
// would return the following:
{
  "user": true,
  "body": true
}

// A request to /message/body.json?shallow=true
// would simply return:
"Hello!"

Hãy thử yêu cầu curl này:

curl 'https://docs-examples.firebaseio.com/rest/retrieving-data.json?shallow=true&print=pretty'

hết giờ

Sử dụng tham số này để giới hạn thời gian đọc ở phía máy chủ. Nếu yêu cầu đọc không hoàn tất trong thời gian quy định, thì yêu cầu đó sẽ kết thúc bằng lỗi HTTP 400. Điều này đặc biệt hữu ích khi bạn dự kiến sẽ có một lượng nhỏ dữ liệu được chuyển và không muốn chờ quá lâu để tìm nạp một cây con có khả năng rất lớn. Thời gian đọc thực tế có thể khác nhau tuỳ thuộc vào kích thước dữ liệu và bộ nhớ đệm.

Chỉ định timeouts bằng định dạng sau: 3ms, 3s hoặc 3min, kèm theo một số và một đơn vị. Nếu bạn không chỉ định, thì timeout tối đa của 15min sẽ được áp dụng. Nếu timeout không dương hoặc vượt quá giá trị tối đa, yêu cầu sẽ bị từ chối kèm theo lỗi HTTP 400. Trong ví dụ sau, yêu cầu GET bao gồm timeout là 10 giây.

curl 'https://docs-examples.firebaseio.com/rest/retrieving-data.json?timeout=10s'

Lọc dữ liệu

Chúng ta có thể tạo các truy vấn để lọc dữ liệu dựa trên nhiều yếu tố. Để bắt đầu, bạn chỉ định cách bạn muốn lọc dữ liệu bằng cách sử dụng tham số orderBy. Sau đó, bạn kết hợp orderBy với bất kỳ tham số nào trong số 5 tham số còn lại: limitToFirst, limitToLast, startAt, endAtequalTo.

Vì tất cả chúng tôi tại Firebase đều cho rằng khủng long khá thú vị, nên chúng tôi sẽ sử dụng một đoạn mã từ cơ sở dữ liệu mẫu về các thông tin thực tế về khủng long để minh hoạ cách bạn có thể lọc dữ liệu:

{
  "lambeosaurus": {
    "height": 2.1,
    "length": 12.5,
    "weight": 5000
  },
  "stegosaurus": {
    "height": 4,
    "length": 9,
    "weight": 2500
  }
}

Chúng ta có thể lọc dữ liệu theo một trong ba cách: theo khoá con, theo khoá hoặc theo giá trị. Một truy vấn bắt đầu bằng một trong các tham số này, sau đó phải được kết hợp với một hoặc nhiều tham số sau: startAt, endAt, limitToFirst, limitToLast hoặc equalTo.

Lọc theo một khoá con cụ thể

Chúng ta có thể lọc các nút theo một khoá con chung bằng cách truyền khoá đó đến tham số orderBy. Ví dụ: để truy xuất tất cả khủng long có chiều cao lớn hơn 3, chúng ta có thể làm như sau:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="height"&startAt=3&print=pretty'

Mọi nút không có khoá con mà chúng ta đang lọc sẽ được sắp xếp với giá trị null. Để biết thông tin chi tiết về cách sắp xếp dữ liệu, hãy xem phần Cách sắp xếp dữ liệu.

Firebase cũng hỗ trợ các truy vấn được sắp xếp theo các phần tử con được lồng sâu, thay vì chỉ các phần tử con ở cấp độ thấp hơn. Điều này sẽ hữu ích nếu bạn có dữ liệu được lồng sâu như sau:

{
  "lambeosaurus": {
    "dimensions": {
      "height" : 2.1,
      "length" : 12.5,
      "weight": 5000
    }
  },
  "stegosaurus": {
    "dimensions": {
      "height" : 4,
      "length" : 9,
      "weight" : 2500
    }
  }
}

Để truy vấn chiều cao ngay bây giờ, chúng ta sẽ sử dụng đường dẫn đầy đủ đến đối tượng thay vì một khoá duy nhất:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="dimensions/height"&startAt=3&print=pretty'

Mỗi lần, các truy vấn chỉ có thể lọc theo một khoá. Việc sử dụng tham số orderBy nhiều lần trên cùng một yêu cầu sẽ gây ra lỗi.

Lọc theo khoá

Chúng ta cũng có thể lọc các nút theo khoá bằng cách sử dụng tham số orderBy="$key". Ví dụ sau đây truy xuất tất cả các loài khủng long có tên bắt đầu bằng chữ cái a đến m:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="$key"&startAt="a"&endAt="m"&print=pretty'

Lọc theo giá trị

Chúng ta có thể lọc các nút theo giá trị của khoá con bằng cách sử dụng tham số orderBy="$value". Giả sử các chú khủng long đang tham gia một cuộc thi thể thao và chúng ta đang theo dõi điểm số của chúng theo định dạng sau:

{
  "scores": {
    "bruhathkayosaurus": 55,
    "lambeosaurus": 21,
    "linhenykus": 80,
    "pterodactyl": 93,
    "stegosaurus": 5,
    "triceratops": 22
  }
}

Để truy xuất tất cả các loài khủng long có điểm số cao hơn 50, chúng ta có thể đưa ra yêu cầu sau:

curl 'https://dinosaur-facts.firebaseio.com/scores.json?orderBy="$value"&startAt=50&print=pretty'

Hãy xem phần Cách sắp xếp dữ liệu để biết giải thích về cách sắp xếp các giá trị null, boolean, chuỗi và đối tượng khi sử dụng orderBy="$value".

Lọc phức tạp

Chúng ta có thể kết hợp nhiều thông số để tạo các truy vấn phức tạp hơn.

Giới hạn truy vấn

Các tham số limitToFirstlimitToLast được dùng để đặt số lượng tối đa trẻ em mà bạn sẽ nhận được dữ liệu. Nếu đặt giới hạn là 100, chúng ta sẽ chỉ nhận được tối đa 100 phần tử con phù hợp. Nếu có ít hơn 100 thông báo được lưu trữ trong cơ sở dữ liệu, chúng ta sẽ nhận được mọi thông báo. Tuy nhiên, nếu có hơn 100 thư, chúng tôi sẽ chỉ nhận được dữ liệu cho 100 thư trong số đó. Đây sẽ là 100 thông báo đầu tiên theo thứ tự nếu chúng ta đang sử dụng limitToFirst hoặc 100 thông báo cuối cùng theo thứ tự nếu chúng ta đang sử dụng limitToLast.

Bằng cách sử dụng cơ sở dữ liệu về khủng long và orderBy, chúng ta có thể tìm thấy 2 loài khủng long nặng nhất:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="weight"&limitToLast=2&print=pretty'

Tương tự, chúng ta có thể tìm thấy 2 loài khủng long ngắn nhất bằng cách sử dụng limitToFirst:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="height"&limitToFirst=2&print=pretty'

Chúng ta cũng có thể thực hiện các truy vấn giới hạn bằng orderBy="$value". Nếu muốn tạo một bảng xếp hạng với 3 vận động viên thể thao khủng long có điểm số cao nhất, chúng ta có thể làm như sau:

curl 'https://dinosaur-facts.firebaseio.com/scores.json?orderBy="$value"&limitToLast=3&print=pretty'

Truy vấn theo phạm vi

Việc sử dụng startAt, endAtequalTo cho phép chúng ta chọn điểm bắt đầu và điểm kết thúc tuỳ ý cho các truy vấn. Ví dụ: nếu muốn tìm tất cả những con khủng long cao ít nhất 3 mét, chúng ta có thể kết hợp orderBystartAt:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="height"&startAt=3&print=pretty'

Chúng ta có thể dùng endAt để tìm tất cả khủng long có tên đứng trước Pterodactyl theo thứ tự từ điển:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="$key"&endAt="pterodactyl"&print=pretty'

Chúng ta có thể kết hợp startAtendAt để giới hạn cả hai đầu của truy vấn. Ví dụ sau đây tìm tất cả các loài khủng long có tên bắt đầu bằng chữ "b":

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="$key"&startAt="b"&endAt="b\uf8ff"&print=pretty'

Truy vấn theo dải cũng hữu ích khi bạn cần phân trang dữ liệu.

Đang kết hợp

Chúng ta có thể kết hợp tất cả các kỹ thuật này để tạo ra các truy vấn phức tạp. Ví dụ: có thể bạn muốn tìm tên của tất cả các loài khủng long có chiều cao nhỏ hơn hoặc bằng loài khủng long mà chúng ta yêu thích, Stegosaurus:

MY_FAV_DINO_HEIGHT=`curl "https://dinosaur-facts.firebaseio.com/dinosaurs/stegosaurus/height.json"`
curl "https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy=\"height\"&endAt=${MY_FAV_DINO_HEIGHT}&print=pretty"

Cách sắp xếp dữ liệu

Phần này giải thích cách dữ liệu của bạn được sắp xếp khi sử dụng từng thông số lọc trong số 3 thông số.

orderBy

Khi sử dụng orderBy với tên của một khoá con, dữ liệu chứa khoá con được chỉ định sẽ được sắp xếp như sau:

  1. Những trẻ có giá trị null cho khoá trẻ được chỉ định sẽ xuất hiện trước.
  2. Tiếp theo là các phần tử con có giá trị false cho khoá con đã chỉ định. Nếu nhiều thành phần con có giá trị false, thì các thành phần con đó sẽ được sắp xếp theo thứ tự từ điển theo khoá.
  3. Tiếp theo là các phần tử con có giá trị true cho khoá con đã chỉ định. Nếu nhiều thành phần con có giá trị true, thì các thành phần con đó sẽ được sắp xếp theo thứ tự từ điển theo khoá.
  4. Tiếp theo là các phần tử con có giá trị bằng số, được sắp xếp theo thứ tự tăng dần. Nếu nhiều phần tử con có cùng giá trị số cho nút con được chỉ định, thì chúng sẽ được sắp xếp theo khoá.
  5. Các chuỗi xuất hiện sau các số và được sắp xếp theo thứ tự từ điển tăng dần. Nếu nhiều phần tử con có cùng giá trị cho nút con được chỉ định, thì các phần tử con đó sẽ được sắp xếp theo thứ tự từ điển theo khoá.
  6. Các đối tượng xuất hiện sau cùng và được sắp xếp theo thứ tự từ điển theo khoá theo thứ tự tăng dần.
Kết quả được lọc sẽ được trả về mà không theo thứ tự. Nếu thứ tự dữ liệu là quan trọng, bạn nên sắp xếp kết quả trong ứng dụng sau khi kết quả được trả về từ Firebase.

orderBy="$key"

Khi bạn dùng tham số orderBy="$key" để sắp xếp dữ liệu, dữ liệu sẽ được trả về theo thứ tự tăng dần theo khoá như sau. Xin lưu ý rằng khoá chỉ có thể là chuỗi.

  1. Trẻ em có khoá có thể phân tích cú pháp dưới dạng số nguyên 32 bit sẽ xuất hiện trước, được sắp xếp theo thứ tự tăng dần.
  2. Tiếp theo là các phần tử con có giá trị chuỗi làm khoá, được sắp xếp theo thứ tự từ điển tăng dần.

orderBy="$value"

Khi bạn dùng tham số orderBy="$value" để sắp xếp dữ liệu, các thành phần con sẽ được sắp xếp theo giá trị của chúng. Tiêu chí sắp xếp giống như dữ liệu được sắp xếp theo khoá con, ngoại trừ việc giá trị của nút được dùng thay vì giá trị của một khoá con cụ thể.

orderBy="$priority"

Khi sử dụng tham số orderBy="$priority" để sắp xếp dữ liệu, thứ tự của các thành phần con được xác định theo mức độ ưu tiên và khoá của chúng như sau. Xin lưu ý rằng giá trị mức độ ưu tiên chỉ có thể là số hoặc chuỗi.

  1. Trẻ em không có mức độ ưu tiên (mặc định) sẽ được ưu tiên trước.
  2. Tiếp theo là trẻ em có số thứ tự ưu tiên. Chúng được sắp xếp theo thứ tự ưu tiên từ nhỏ đến lớn.
  3. Trẻ em có chuỗi là ưu tiên sẽ đến sau cùng. Chúng được sắp xếp theo thứ tự từ điển theo mức độ ưu tiên.
  4. Bất cứ khi nào hai phần tử con có cùng mức độ ưu tiên (kể cả khi không có mức độ ưu tiên), chúng sẽ được sắp xếp theo khoá. Các khoá số xuất hiện trước (được sắp xếp theo số), theo sau là các khoá còn lại (được sắp xếp theo từ điển).

Để biết thêm thông tin về mức độ ưu tiên, hãy xem tài liệu tham khảo về API.

Phát trực tuyến từ API REST

Các điểm cuối REST của Firebase hỗ trợ giao thức EventSource/Server-Sent Events, giúp bạn dễ dàng truyền trực tuyến các thay đổi đến một vị trí duy nhất trong cơ sở dữ liệu Firebase của chúng tôi.

Để bắt đầu phát trực tiếp, chúng ta cần làm những việc sau:

  1. Đặt tiêu đề Accept của ứng dụng khách thành text/event-stream
  2. Tôn trọng lệnh chuyển hướng HTTP, đặc biệt là mã trạng thái HTTP 307
  3. Thêm tham số truy vấn auth nếu vị trí cơ sở dữ liệu Firebase yêu cầu quyền đọc

Đổi lại, máy chủ sẽ gửi các sự kiện được đặt tên khi trạng thái của dữ liệu tại URL được yêu cầu thay đổi. Cấu trúc của những thông báo này tuân theo giao thức EventSource:

event: event name
data: JSON encoded data payload

Máy chủ có thể gửi các sự kiện sau:

put Dữ liệu được mã hoá bằng JSON sẽ là một đối tượng có hai khoá: đường dẫn và dữ liệu
Đường dẫn trỏ đến một vị trí tương ứng với URL yêu cầu
Ứng dụng nên thay thế tất cả dữ liệu tại vị trí đó trong bộ nhớ đệm bằng dữ liệu được cung cấp trong thông báo
bản vá Dữ liệu được mã hoá JSON sẽ là một đối tượng có hai khoá: đường dẫn và dữ liệu
Đường dẫn trỏ đến một vị trí tương ứng với URL yêu cầu
Đối với mỗi khoá trong dữ liệu, ứng dụng nên thay thế khoá tương ứng trong bộ nhớ đệm bằng dữ liệu cho khoá đó trong thông báo
keep-alive Dữ liệu cho sự kiện này là giá trị rỗng, bạn không cần làm gì cả
hủy Dữ liệu cho sự kiện này là rỗng
Sự kiện này sẽ được gửi nếu Firebase Realtime Database Security Rules khiến việc đọc tại vị trí được yêu cầu không còn được phép nữa
auth_revoked Dữ liệu cho sự kiện này là một chuỗi cho biết thông tin đăng nhập đã hết hạn
Sự kiện này sẽ được gửi khi tham số uỷ quyền được cung cấp không còn hợp lệ

Dưới đây là ví dụ về một nhóm sự kiện mà máy chủ có thể gửi:

// Set your entire cache to {"a": 1, "b": 2}
event: put
data: {"path": "/", "data": {"a": 1, "b": 2}}


// Put the new data in your cache under the key 'c', so that the complete cache now looks like:
// {"a": 1, "b": 2, "c": {"foo": true, "bar": false}}
event: put
data: {"path": "/c", "data": {"foo": true, "bar": false}}


// For each key in the data, update (or add) the corresponding key in your cache at path /c,
// for a final cache of: {"a": 1, "b": 2, "c": {"foo": 3, "bar": false, "baz": 4}}
event: patch
data: {"path": "/c", "data": {"foo": 3, "baz": 4}}

Nếu bạn đang sử dụng Go, hãy xem Firego, một trình bao bọc bên thứ ba xung quanh Firebase REST và Streaming API.