Retrieving Data

This document covers the basics of retrieving data and how to order and filter Firebase data.

Before you begin

Before you can use the Firebase Realtime Database, you will need to create a Firebase project, and add the Firebase Unity SDK packages to your Unity project.

Setup:

Prerequisites

Android

iOS

  • Unity 5.0 or later
  • Xcode 7.0 or later

If you don't have a Unity project already, you can download one of our quickstart samples and experiment with a specific Firebase feature. If you're using a quickstart, remember to get the bundle identifier from the project settings; you need it for the next step.

Set up your app in the Firebase console

To add Firebase to your app, you need a Firebase project and a Firebase configuration file for your app.

Create a Firebase project in the Firebase console if you don't already have one. If you already have an existing Google project associated with your mobile app, click Import Google Project. Otherwise, click Create New Project.

Android

  1. Click Add Firebase to your Android app and follow the setup steps. If you're importing an existing Google project, this may happen automatically and you can just download the config file.
  2. When prompted, enter your app's package name. It's important to enter the package name your app is using; this can only be set when you add an app to your Firebase project.
  3. Download a google-services.json file when instructed. You can redownload this file again at any time.
  4. Copy this file to anywhere inside your project's assets folder.

IOs

  1. Click Add Firebase to your iOS app and follow the setup steps. If you're importing an existing Google project, this may happen automatically and you can just download the config file.
  2. When prompted, enter your app's bundle ID. It's important to enter the bundle ID your app is using; this can only be set when you add an app to your Firebase project.
  3. Download a GoogleService-Info.plist file when instructed. You can redownload this file again at any time.
  4. Add the GoogleService-Info.plist file to the project.

  5. Drag the GoogleService-Info.plist downloaded from the Firebase console into any folder in the Unity project.

Add the Firebase Unity SDK to your app

  1. Download the Firebase Unity SDK.
  2. Select the Assets > Import Package > Custom Package menu item.
  3. Import the FirebaseDatabase.unitypackage package from the Firebase Unity SDK, downloaded previously.
  4. When the Import Unity Package window appears, click the Import button.

Build your app

Android

  1. Select the File > Build Settings menu option.
  2. Select Android in the Platform list.
  3. Click Switch Platform to select Android as the target platform.
  4. Wait for the spinner (compiling) icon in the bottom right corner of the Unity status bar to stop.
  5. Click Build and Run.

iOS

  1. Select the File > Build Settings menu option.
  2. Select iOS in the Platform list.
  3. Click Switch Platform to select iOS as the target platform.
  4. Wait for the spinner (compiling) icon in the bottom right corner of the Unity status bar to stop.
  5. Click Build and Run.

Retrieving Data

Firebase data is retrieved by either a one time call to GetValueAsync() or attaching to an event on a FirebaseDatabase reference. The event listener is called once for the initial state of the data and again anytime the data changes.

Get a DatabaseReference

To read data from the database, you need an instance of DatabaseReference:

using Firebase;
using Firebase.Database;
using Firebase.Unity.Editor;

public class MyScript: MonoBehaviour {
  void Start() {
    // Set up the Editor before calling into the realtime database.
    FirebaseApp.DefaultInstance.SetEditorDatabaseUrl("https://YOUR-FIREBASE-APP.firebaseio.com/");

    // Get the root reference location of the database.
    DatabaseReference reference = FirebaseDatabase.DefaultInstance.RootReference;
  }
}

Read data once

You can use the GetValueAsync 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.

    FirebaseDatabase.DefaultInstance
      .GetReference("Leaders")
      .GetValueAsync().ContinueWith(task => {
        if (task.IsFaulted) {
          // Handle the error...
        }
        else if (task.IsCompleted) {
          DataSnapshot snapshot = task.Result;
          // Do something with snapshot...
        }
      });

Listen for events

You can add event listeners to subscribe on changes to data:

Event Typical usage
ValueChanged Read and listen for changes to the entire contents of a path.
ChildAdded Retrieve lists of items or listen for additions to a list of items. Suggested use with ChildChanged and ChildRemoved to monitor changes to lists.
ChildChanged Listen for changes to the items in a list. Use with ChildAdded and ChildRemoved to monitor changes to lists.
ChildRemoved Listen for items being removed from a list. Use with ChildAdded and ChildChanged to monitor changes to lists.
ChildMoved Listen for changes to the order of items in an ordered list. ChildMoved events always follow the ChildChanged event that caused the item's order to change (based on your current order-by method).

ValueChanged event

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

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

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders")
        .ValueChanged += HandleValueChanged;
    }

    void HandleValueChanged(object sender, ValueChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

ValueChangedEventArgs contains a DataSnapshot that contains the data at the specified location in the database at the time of the event. Calling Value on a snapshot returns a Dictionary<string, object> representing the data. If no data exists at the location, calling Value returns null.

In this example, args.DatabaseError is also examined to see if the read is canceled. For example, a read can be canceled if the client doesn't have permission to read from a Firebase database location. The DatabaseError will indicate why the failure occurred.

You can later unsubscribe from the event using any DatabaseReference that has the same path. DatabaseReference instances are ephemeral and can be thought of as a way to access any path and query.

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders")
        .ValueChanged -= HandleValueChanged; // unsubscribe from ValueChanged.
    }

Child events

Child events are triggered in response to specific operations that happen to the children of a node from an operation such as a new child added through the Push() method or a child being updated through the UpdateChildrenAsync() method. Each of these together can be useful for listening to changes to a specific node in a database. For example, a game might use these methods together to monitor activity in the comments of a game session, as shown below:

      var ref = FirebaseDatabase.DefaultInstance
      .GetReference("GameSessionComments");

      ref.ChildAdded += HandleChildAdded;
      ref.ChildChanged += HandleChildChanged;
      ref.ChildRemoved += HandleChildRemoved;
      ref.ChildMoved += HandleChildMoved;
    }

    void HandleChildAdded(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

    void HandleChildChanged(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

    void HandleChildRemoved(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

    void HandleChildMoved(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

The ChildAdded event is typically used to retrieve a list of items in a Firebase database. The ChildAdded event is raised once for each existing child and then again every time a new child is added to the specified path. The listener is passed a snapshot containing the new child's data.

The ChildChanged event is raised any time a child node is modified. This includes any modifications to descendants of the child node. It is typically used in conjunction with the ChildAdded and ChildRemoved events to respond to changes to a list of items. The snapshot passed to the event listener contains the updated data for the child.

The ChildRemoved event is triggered when an immediate child is removed. It is typically used in conjunction with the ChildAdded and ChildChanged callbacks. The snapshot passed to the event callback contains the data for the removed child.

The ChildMoved event is triggered whenever the ChildChanged event is raised by an update that causes reordering of the child. It is used with data that is ordered with OrderByChild or OrderByValue.

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.

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 on a score leaderboard ordered by score.

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders").OrderByChild("score")
        .ValueChanged += HandleValueChanged;
    }

    void HandleValueChanged(object sender, ValueChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

This defines a query that when combined with a valuechanged event listener synchronizes the client with the leaderboard in the database, ordered by the score of each entry. You can read more about structuring your data efficiently in Structure Your Database.

The call to the OrderByChild() method specifies the child key to order the results by. In this case, results are sorted by the value of the "score" value in each child. For more information on how other data types are ordered, see How query data is ordered.

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 ChildAdded callbacks. If you have fewer than 100 items stored in your Firebase database, an ChildAdded callback fires for each item.

As items change, you receive ChildAdded callbacks for items that enter the query and ChildRemoved 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:

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders").OrderByChild("score").LimitToLast(1)
        .ValueChanged += HandleValueChanged;
    }

    void HandleValueChanged(object sender, ValueChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

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.

Send feedback about...

Need help? Visit our support page.