Reading Data with GET
We can read data from our Firebase database by issuing a
GET
request to its URL
endpoint. Let's continue with our blog example from the previous section and read all of our
blog post data:
curl 'https://docs-examples.firebaseio.com/fireblog/posts.json?print=pretty'
A successful request will be indicated by a
200 OK
HTTP status code, and the
response will contain the data we're retrieving.
Adding URI Parameters
The REST API accepts several query parameters when reading data from our Firebase database.
Listed below are the most commonly used parameters. For a full list, refer to the
REST API Reference
.
auth
The
auth
request parameter allows access to data protected by
Firebase Realtime Database Security Rules
, and is
supported by all request types. The argument can either be your Firebase app's secret or an
authentication token, as described in the
Users in Firebase Projects
. In the following example we send a
GET
request with an
auth
parameter, where
CREDENTIAL
is either your Firebase app's secret or an
authentication token:
curl 'https://docs-examples.firebaseio.com/auth-example.json?auth=CREDENTIAL'
print
Specifying
print=pretty
returns the data in a human-readable format.
curl 'https://docs-examples.firebaseio.com/fireblog/posts.json?print=pretty'
Specifying
print=silent
returns a
204 No Content
on success.
curl 'https://docs-examples.firebaseio.com/fireblog/posts.json?print=silent'
callback
To make REST calls from a web browser across domains you can use
JSONP
to wrap the response in a JavaScript
callback function. Add
callback=
to have the REST API wrap the returned data in the
callback function you specify. For example:
<script>
function gotData(data) {
console.log(data);
}
</script>
<script src="https://docs-examples.firebaseio.com/fireblog/posts.json?callback=gotData">
shallow
This is an advanced feature, designed to help you work with large datasets without needing to
download everything. To use it, add
shallow=true
as a parameter. This will limit
the depth of the data returned. If the data at the location is a JSON primitive (string, number,
or boolean) its value will simply be returned. If the data snapshot at the location is a JSON
object, the values for each key will be truncated to
true
. For example, using
the data below:
{
"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!"
Try it out with this
curl
request:
curl 'https://docs-examples.firebaseio.com/rest/retrieving-data.json?shallow=true&print=pretty'
timeout
Use this to limit how long the read takes on the server side. If a read
request doesn't finish within the allotted time, it terminates with an HTTP
400 error. This is particularly useful when you expect a small data transfer
and don't want to wait too long to fetch a potentially huge subtree. Actual
read time might vary based on data size and caching.
Specify
timeouts
using the following format:
3ms
,
3s
, or
3min
, with a number and a unit. If not
specified, the maximum
timeout
of
15min
will be
applied. If the
timeout
is not positive, or exceeds the maximum,
the request will be rejected with an HTTP 400 error.
In the following example, the
GET
request includes a
timeout
of 10 seconds.
curl 'https://docs-examples.firebaseio.com/rest/retrieving-data.json?timeout=10s'
Filtering Data
We can construct queries to filter data based on various factors. To start, you specify how you want your data to be filtered using the
orderBy
parameter. Then, you combine
orderBy
with any of the other five parameters:
limitToFirst
,
limitToLast
,
startAt
,
endAt
,
and
equalTo
.
Since all of us at Firebase think dinosaurs are pretty cool, we'll use
a snippet from a sample database of dinosaur facts to demonstrate how
you can filter data:
{
"lambeosaurus": {
"height": 2.1,
"length": 12.5,
"weight": 5000
},
"stegosaurus": {
"height": 4,
"length": 9,
"weight": 2500
}
}
We can filter data in one of three ways: by
child key
, by
key
, or by
value
. A query starts with one of these parameters, and then must be combined with one or more of the following parameters:
startAt
,
endAt
,
limitToFirst
,
limitToLast
, or
equalTo
.
Filtering by a specified child key
We can filter nodes by a common child key by passing that key to the
orderBy
parameter. For example, to retrieve all dinosaurs with a height greater than 3, we can do the following:
curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="height"&startAt=3&print=pretty'
Any node that does not have the child key we're filtering on will be sorted with a value of
null
. For details on how data is
ordered, see
How Data is Ordered
.
Firebase also supports queries ordered by deeply nested children, rather than only children one level down. This is useful if you have deeply nested data like this:
{
"lambeosaurus": {
"dimensions": {
"height" : 2.1,
"length" : 12.5,
"weight": 5000
}
},
"stegosaurus": {
"dimensions": {
"height" : 4,
"length" : 9,
"weight" : 2500
}
}
}
To query the height now, we use the full path to the object rather than a single key:
curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="dimensions/height"&startAt=3&print=pretty'
Queries can only filter by one key at a time. Using the
orderBy
parameter multiple
times on the same request throws an error.
Filtering by key
We can also filter nodes by their keys using the
orderBy="$key"
parameter. The
following example retrieves all dinosaurs with a name starting with the letter
a
through
m
:
curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="$key"&startAt="a"&endAt="m"&print=pretty'
Filtering by value
We can filter nodes by the value of their child keys using the
orderBy="$value"
parameter. Let's say the dinosaurs are having a dino sports competition and we're keeping
track of their scores in the following format:
{
"scores": {
"bruhathkayosaurus": 55,
"lambeosaurus": 21,
"linhenykus": 80,
"pterodactyl": 93,
"stegosaurus": 5,
"triceratops": 22
}
}
To retrieve all dinosaurs with a score higher than 50, we could make the following request:
curl 'https://dinosaur-facts.firebaseio.com/scores.json?orderBy="$value"&startAt=50&print=pretty'
See
How Data is Ordered
for an explanation on
how
null
, boolean, string, and object values are sorted when using
orderBy="$value"
.
Complex Filtering
We can combine multiple parameters to construct more complex queries.
Limit Queries
The
limitToFirst
and
limitToLast
parameters are used to set a
maximum number of children for which to receive data. If we set a limit of 100, we will only
receive up to 100 matching children. If we have less than 100 messages stored in our
database, we will receive every child. However, if we have over 100 messages, we will only
receive data for 100 of those messages. These will be the first 100 ordered messages if we are
using
limitToFirst
or the last 100 ordered messages if we are using
limitToLast
.
Using our dinosaur facts database and
orderBy
, we can find the two
heaviest dinosaurs:
curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="weight"&limitToLast=2&print=pretty'
Similarly, we can find the two shortest dinosaurs by using
limitToFirst
:
curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="height"&limitToFirst=2&print=pretty'
We can also conduct limit queries with
orderBy="$value"
. If we want to create a
leaderboard with the top three highest scoring dino sports competitors, we could do the
following:
curl 'https://dinosaur-facts.firebaseio.com/scores.json?orderBy="$value"&limitToLast=3&print=pretty'
Range Queries
Using
startAt
,
endAt
, and
equalTo
allows us to choose
arbitrary starting and ending points for our queries. For example, if we wanted to find all
dinosaurs that are at least three meters tall, we can combine
orderBy
and
startAt
:
curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="height"&startAt=3&print=pretty'
We can use
endAt
to find all dinosaurs whose names come before Pterodactyl
lexicographically:
curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="$key"&endAt="pterodactyl"&print=pretty'
We can combine
startAt
and
endAt
to limit both ends of our query.
The following example finds all dinosaurs whose name starts with the letter "b":
curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="$key"&startAt="b"&endAt="b\uf8ff"&print=pretty'
Range queries are also useful when you need to paginate your data.
Putting it all together
We can combine all of these techniques to create complex queries. For example, maybe you want
to find the name of all dinosaurs that are shorter than or equal in height to our favorite
kind, 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"
How Data is Ordered
This section explains how your data is ordered when using each of the three filtering parameters.
orderBy
When using
orderBy
with the name of a child key, data that contains the specified
child key will be ordered as follows:
-
Children with a
null
value for the specified child key come first.
-
Children with a value of
false
for the specified child key come next. If
multiple children have a value of
false
, they are sorted
lexicographically
by key.
-
Children with a value of
true
for the specified child key come next. If
multiple children have a value of
true
, they are sorted lexicographically by
key.
-
Children with a numeric value come next, sorted in ascending order. If multiple children
have the same numerical value for the specified child node, they are sorted by key.
-
Strings come after numbers, and are sorted lexicographically in ascending order. If multiple
children have the same value for the specified child node, they are ordered
lexicographically by key.
-
Objects come last, and sorted lexicographically by key in ascending order.
The filtered results are returned unordered. If the order of your data is important you should sort the results in your application after they are returned from Firebase.
orderBy="$key"
When using the
orderBy="$key"
parameter to sort your data, data will be returned
in ascending order by key as follows. Keep in mind that keys can only be strings.
-
Children with a key that can be parsed as a 32-bit integer come first, sorted in ascending
order.
-
Children with a string value as their key come next, sorted lexicographically in ascending
order.
orderBy="$value"
When using the
orderBy="$value"
parameter to sort your data, children will be
ordered by their value. The ordering criteria is the same as data ordered by a child key,
except the value of the node is used instead of the value of a specified child key.
orderBy="$priority"
When using the
orderBy="$priority"
parameter to sort your data, the ordering of
children is determined by their priority and key as follows. Keep in mind that priority values
can only be numbers or strings.
-
Children with no priority (the default) come first.
-
Children with a number as their priority come next. They are sorted numerically by priority,
small to large.
-
Children with a string as their priority come last. They are sorted lexicographically by
priority.
-
Whenever two children have the same priority (including no priority), they are sorted by key.
Numeric keys come first (sorted numerically), followed by the remaining keys (sorted
lexicographically).
For more information on priorities, see the
API reference
.
Streaming from the REST API
Firebase REST endpoints support the
EventSource /
Server-Sent Events
protocol, making it easy to stream changes to a single location in our
Firebase database.
To get started with streaming, we will need to do the following:
-
Set the client's Accept header to
text/event-stream
-
Respect HTTP Redirects, in particular HTTP status code 307
-
Include the
auth
query parameter if the Firebase database location requires
permission to read
In return, the server will send named events as the state of the data at the requested URL
changes. The structure of these messages conforms to the EventSource protocol:
event: event name
data: JSON encoded data payload
The server may send the following events:
put
|
The JSON-encoded data will be an object with two keys: path and data
The path points to a location relative to the request URL
The client should replace all of the data at that location in its cache with the data given in the message
|
patch
|
The JSON-encoded data will be an object with two keys: path and data
The path points to a location relative to the request URL
For each key in the data, the client should replace the corresponding key in its cache with the data for that key in the message
|
keep-alive
|
The data for this event is null, no action is required
|
cancel
|
The data for this event is null
This event will be sent if the Firebase Realtime Database Security Rules cause a read at the requested location to no longer be allowed
|
auth_revoked
|
The data for this event is a string indicating that a the credential has expired
This event will be sent when the supplied auth parameter is no longer valid
|
Below is an example of a set of events that the server may send:
// 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}}
If you're using Go, check out
Firego
, a
third-party wrapper around the Firebase REST and Streaming APIs.