Realtime Database

The Firebase Realtime Database stores and synchronizes data using a NoSQL cloud database. Data is synchronized across all clients in realtime, and remains available when your app goes offline.

Get Started with Firebase Realtime Database

Create a Database

  1. Navigate to the Realtime Database section of the Firebase console. You'll be prompted to select an existing Firebase project. Follow the database creation workflow.

  2. Select a starting mode for your Firebase Security Rules:

    Test mode
    Good for getting started with the mobile and web client libraries, but allows anyone to read and overwrite your data. After testing, make sure to review the Understand Firebase Realtime Database Rules section.

    Locked mode
    Denies all reads and writes from mobile and web clients. Your authenticated application servers can still access your database.

  3. Choose a region for the database. Depending on your choice of region, the database namespace will be of the form <databaseName>.firebaseio.com or <databaseName>.<region>.firebasedatabase.app. For more information, see select locations for your project.

  4. Click Done.

Setting up Restricted Access

If you do not want to use public access you can add Firebase Authentication to your app to control access to the database.

Saving Data with Firebase Realtime Database

Get a DatabaseReference

To write data to the Database, you need an instance of DatabaseReference:

BlueprintsC++
// C++ example code not available yet.

Saving Data

There are four methods for writing data to the Firebase Realtime Database:

Method Common uses
SetValue() Write or replace data to a defined path, such as users/<user-id>/<username>.
PushChild() Add to a list of data. Every time you call Push(), Firebase generates a unique key that can also be used as a unique identifier, such as user-scores/<user-id>/<unique-score-id>.
UpdateChildren() Update some of the keys for a defined path without replacing all of the data.
RunTransaction() Update complex data that could be corrupted by concurrent updates.

Write, Update, or Delete Data at a Reference

Basic Write Operations

For basic write operations, you can use the SetValue() method to save data to a specified reference, replacing any existing data at that path:

Using SetValue() in this way overwrites data at the specified location, including any child nodes. However, you can still update a child without rewriting the entire object. If you want to allow users to update their profiles you could update the username as follows:

BlueprintsC++
// C++ example code not available yet.

Append to a list of data

Use the PushChild() method to append data to a list in multiuser applications. The PushChild() method generates a unique key every time a new child is added to the specified Firebase reference. By using these auto-generated keys for each new element in the list, several clients can add children to the same location at the same time without write conflicts. The unique key generated by PushChild() is based on a timestamp, so list items are automatically ordered chronologically.

You can use the reference to the new data returned by the PushChild() method to get the value of the child's auto-generated key or set data for the child. Calling GetKey() on a PushChild() reference returns the value of the auto-generated key.

Delete data

The simplest way to delete data is to call RemoveValue() on a reference to the location of that data.

BlueprintsC++
// C++ example code not available yet.

You can also delete by specifying a null Variant as the value for another write operation such as SetValue() or UpdateChildren(). You can use this technique with UpdateChildren() to delete multiple children in a single API call.

BlueprintsC++
// C++ example code not available yet.

Write data offline

If a client loses its network connection, your app will continue functioning correctly.

Every client connected to a Firebase database maintains its own internal version of any active data. When data is written, it's written to this local version first. The Firebase client then synchronizes that data with the remote database servers and with other clients on a "best-effort" basis.

As a result, all writes to the database trigger local events immediately, before any data is written to the server. This means your app remains responsive regardless of network latency or connectivity.

Once connectivity is reestablished, your app receives the appropriate set of events so that the client syncs with the current server state, without having to write any custom code.

Setup Disconnection Handler

Operations can be setup on the Database when a user disconnects.

BlueprintsC++
// C++ example code not available yet.

The following operations are available:

  1. Remove Value
  2. Set Value
  3. Set Value and Priority
  4. Update Children

Retrieving Data with Firebase Realtime Database

Read Data Once

You can use the GetValue() method to read a static snapshot of the contents at a given path once. The task result will contain a snapshot containing all data at that location, including child data. If there is no data, the snapshot returned is null.

BlueprintsC++
// C++ example code not available yet.

The data from the snapshot can then be read as followed when we get a node with children:

BlueprintsC++
// C++ example code not available yet.

Listen for Events

Available Events

Several events are available on a reference to handle data or structure changes:

Event Name Details
OnChildAdded Called when a child has been added to the reference watched.
OnChildChanged Called when a child of the reference we watch has been modified.
OnChildMoved Called when a child of the reference we watch has been moved.
OnChildRemoved Called when a child of the reference we watch has been removed.
OnCancelled Called when the watch has been cancelled.
OnValueChanged Called when the value watched has changed.

Value Listener

You can use the OnValueChanged callbacks to subscribe to changes to the contents at a given path. This callback is triggered once when the listener is attached and again every time the data, including children, changes. The callback is passed a snapshot containing all data at that location, including child data. If there is no data, the snapshot returned is null.

Important: The OnValueChanged event is called every time data is changed at the specified database reference, including changes to children. To limit the size of your snapshots, attach only at the highest level needed for watching changes. For example, attaching a listener to the root of your database is not recommended.

The following example demonstrates a game retrieving the scores of a leaderboard from the database when it changed:

BlueprintsC++
// C++ example code not available yet.

Sorting and Filtering Data

You can use the Realtime Database Query class to retrieve data sorted by key, by value, or by value of a child. You can also filter the sorted result to a specific number of results or a range of keys or values.

Note: Filtering and sorting can be expensive, especially when done on the client. If your app uses queries, define the .indexOn rule to index those keys on the server and improve query performance as described in Indexing Your Data.

Sort Data

To retrieve sorted data, start by specifying one of the order-by methods to determine how results are ordered:

Method Usage
OrderByChild() Order results by the value of a specified child key.
OrderByKey() Order results by child keys.
OrderByValue() Order results by child values.

You can only use one order-by method at a time. Calling an order-by method multiple times in the same query throws an error.

The following example demonstrates how you could subscribe to a score leaderboard ordered by score.

BlueprintsC++
// C++ example code not available yet.

Filtering Data

To filter data, you can combine any of the limit or range methods with an order-by method when constructing a query.

Method Usage
LimitToFirst() Sets the maximum number of items to return from the beginning of the ordered list of results.
LimitToLast() Sets the maximum number of items to return from the end of the ordered list of results.
StartAt() Return items greater than or equal to the specified key or value depending on the order-by method chosen.
EndAt() Return items less than or equal to the specified key or value depending on the order-by method chosen.
EqualTo() Return items equal to the specified key or value depending on the order-by method chosen.

Unlike the order-by methods, you can combine multiple limit or range functions. For example, you can combine the StartAt() and EndAt() methods to limit the results to a specified range of values.

Even when there is only a single match for the query, the snapshot is still a list; it just contains a single item.

Limit the Number of Results

You can use the LimitToFirst() and LimitToLast() methods to set a maximum number of children to be synced for a given callback. For example, if you use LimitToFirst() to set a limit of 100, you initially only receive up to 100 OnChildAdded callbacks. If you have fewer than 100 items stored in your Firebase database, an OnChildAdded callback fires for each item.

As items change, you receive OnChildAdded callbacks for items that enter the query and OnChildRemoved callbacks for items that drop out of it so that the total number stays at 100.

For example, the code below returns the top score from a leaderboard:

BlueprintsC++
// C++ example code not available yet.
Filter by key or value

You can use StartAt(), EndAt(), and EqualTo() to choose arbitrary starting, ending, and equivalence points for queries. This can be useful for paginating data or finding items with children that have a specific value.

How query data is ordered

This section explains how data is sorted by each of the order-by methods in the Query class.

OrderByChild

When using OrderByChild(), data that contains the specified child key is ordered as follows:

  1. Children with a null value for the specified child key come first.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. Objects come last and are sorted lexicographically by key in ascending order.
OrderByKey

When using OrderByKey() to sort your data, data is returned in ascending order by key.

  1. Children with a key that can be parsed as a 32-bit integer come first, sorted in ascending order.
  2. Children with a string value as their key come next, sorted lexicographically in ascending order.
OrderByValue

When using OrderByValue(), children are ordered by their value. The ordering criteria are the same as in OrderByChild(), except the value of the node is used instead of the value of a specified child key.