检索数据

本文档将介绍数据检索的基础知识以及如何对 Firebase 数据进行排序和过滤。

开始前的准备工作

您必须先创建一个 Firebase 项目,并将 Firebase Unity SDK 软件包添加到您的 Unity 项目中,然后才能使用 Firebase 实时数据库

设置:

前提条件

Android

  • Unity 5.0 或更高版本
  • Android NDK 版本 10d 或更高版本

iOS

  • Unity 5.0 或更高版本
  • Xcode 8.0 或更高版本

如果您还没有 Unity 项目,可以下载一个快速入门示例,试用一下特定的 Firebase 功能。如果使用快速入门示例,请不要忘记从项目设置中获取软件包标识符,下一步中会用到该标识符。

在 Firebase 控制台中设置您的应用

要将 Firebase 添加到您的应用,您需要有一个 Firebase 项目以及适用于您的应用的 Firebase 配置文件。

如果您还没有 Firebase 项目,请在 Firebase 控制台中创建一个。如果您已经有与自己的移动应用相关联的现有 Google 项目,请点击导入 Google 项目。如果没有,请点击添加项目

Android

  1. 点击将 Firebase 添加到您的 Android 应用,然后按设置步骤操作。如果您是导入现有 Google 项目,系统可能会自动执行这些操作,您只需下载配置文件即可。
  2. 出现提示时,输入应用的软件包名称。请务必输入应用在使用的软件包名称;只有在将应用添加到 Firebase 项目时您才能进行此设置。
  3. 按照说明下载 google-services.json 文件。您随时可以再重新下载此文件
  4. 将此文件复制到项目的资源文件夹内的任意位置。

iOS

  1. 点击将 Firebase 添加到您的 iOS 应用,然后按设置步骤操作。如果您是导入现有 Google 项目,系统可能会自动执行这些操作,您只需下载配置文件即可。
  2. 出现提示时,输入应用的软件包 ID。请务必输入应用在使用的软件包 ID;只有在将应用添加到 Firebase 项目时您才能进行此设置。
  3. 按照说明下载 GoogleService-Info.plist 文件。您随时可以再重新下载此文件
  4. GoogleService-Info.plist 文件添加到项目中。

    • 将从 Firebase 控制台下载的 GoogleService-Info.plist 拖动到 Unity 项目中的任意文件夹内。

将 Firebase Unity SDK 添加到您的应用

  1. 下载 Firebase Unity SDK
  2. 选择“Assets > Import Package > Custom Package”菜单项。
  3. 从之前下载的 Firebase Unity SDK 导入 FirebaseDatabase.unitypackage 软件包。
  4. 当出现 Import Unity Package 窗口时,点击 Import 按钮。

初始化 SDK

Firebase Unity SDK (Android) 需要使用 Google Play 服务。必须先将 Google Play 服务更新为最新版本,然后才能使用该 SDK。应在您的应用开头处添加以下代码,以便检查是否有 Google Play 服务更新,并视情况需要将这些服务更新为 Firebase Unity SDK 要求的版本,然后再调用 SDK 中的任何其他方法。

Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => {
  var dependencyStatus = task.Result;
  if (dependencyStatus == Firebase.DependencyStatus.Available) {
    // Set a flag here indiciating that Firebase is ready to use by your
    // application.
  } else {
    UnityEngine.Debug.LogError(System.String.Format(
      "Could not resolve all Firebase dependencies: {0}", dependencyStatus));
    // Firebase Unity SDK is not safe to use here.
  }
});

编译您的应用

Android

  1. 依次选择 File > Build Settings 菜单选项。
  2. 选择 Platform 列表中的 Android
  3. 点击 Switch Platform,选择 Android 作为目标平台。
  4. 等待 Unity 状态栏右下角的旋转进度条(正在编译)图标停止旋转。
  5. 点击 Build and Run

iOS

  1. 依次选择 File > Build Settings 菜单选项。
  2. 选择 Platform 列表中的 iOS
  3. 点击 Switch Platform,选择 iOS 作为目标平台。
  4. 等待 Unity 状态栏右下角的旋转进度条(正在编译)图标停止旋转。
  5. 点击 Build and Run

检索数据

您可以通过一次性调用 GetValueAsync() 或将某个事件附加到 FirebaseDatabase 引用来检索 Firebase 数据。事件侦听器在数据进入初始状态时会被调用一次,以后每当数据发生更改时都会被再次调用。

获取 DatabaseReference

要从数据库读取数据,您需要一个 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;
  }
}

一次性读取数据

您可以使用 GetValueAsync 方法一次性读取某个给定路径下全部内容的静态快照。任务结果将包括一个快照,其中包含该位置下的所有数据,包括子数据。如果该位置没有任何数据,则返回的快照为 null

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

侦听事件

您可以添加事件侦听器来接收数据更改信息:

事件 典型用法
ValueChanged 读取并侦听对路径中所有内容的更改。
ChildAdded 检索项目列表,或侦听项目列表中是否添加了新项目。建议与 ChildChangedChildRemoved 配合使用以监控列表的更改。
ChildChanged 侦听对列表中的项目做出的更改。与 ChildAddedChildRemoved 配合使用以监控列表的更改。
ChildRemoved 侦听列表中是否有项目被移除。与 ChildAddedChildChanged 配合使用以监控列表的更改。
ChildMoved 侦听经过排序的列表的项目顺序是否有更改。 每当有 ChildChanged 事件导致项目的顺序发生更改(基于您当前的排序依据方法)时,就会触发 ChildMoved 事件。

ValueChanged 事件

您可以使用 ValueChanged 事件来接收有关某个给定路径下内容发生更改的信息。此事件在附加侦听器时触发一次,以后会在每次数据(包括子节点数据)发生更改时再次触发。系统会向事件回调函数传递一个包含该位置下所有数据(包括子节点数据)的快照。如果该位置没有任何数据,则返回的快照为 null

以下示例演示了一款游戏如何从数据库中检索排行榜得分情况:

      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 包括一个 DataSnapshot,其中包含事件发生时数据库中指定位置的数据。调用快照中的 Value 可返回一个表示数据的 Dictionary<string, object>。如果该位置没有任何数据,调用 Value 将返回 null

在此示例中,我们还会检查 args.DatabaseError 以查看读取操作是否已取消。例如,如果客户端没有权限从 Firebase 数据库位置读取数据,则可取消读取操作。DatabaseError 中的信息将指明操作失败的原因。

稍后您可以使用具有相同路径的任何 DatabaseReference 退订事件。DatabaseReference 实例具有临时性质,可以视为访问任何路径和查询的方式。

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

子节点事件

当因为某项操作(例如通过 Push() 方法添加新的子节点,或通过 UpdateChildrenAsync() 方法更新子节点)而使得某个节点的子节点发生更改时,就会触发子节点事件。同时使用所有这些事件有助于侦听数据库中某个特定节点是否有更改。例如,一款游戏可以综合使用这些方法来监控游戏会话评论中的活动,如下所示:

      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
    }

ChildAdded 事件通常用于在 Firebase 数据库中检索项目列表。每个现有的子节点都会引发一次 ChildAdded 事件,并且以后每次向指定的路径添加新的子节点时都会再次引发该事件。系统会向侦听器传递一个包含新子节点数据的快照。

每当有子节点被修改后都会引发 ChildChanged 事件,包括对子节点的后代所做的任何修改。它通常与 ChildAddedChildRemoved 事件结合使用,以便响应对项目列表的各种更改。传递给事件侦听器的快照中将包含子节点更新后的数据。

移除直接子节点后就会触发 ChildRemoved 事件。它通常与 ChildAddedChildChanged 回调函数结合使用。传递给事件回调函数的快照中将包含已移除的子节点的数据。

每当引发 ChildChanged 事件的子节点数据更新操作还会导致子节点重新排序时,系统就会触发 ChildMoved 事件。当数据已通过 OrderByChildOrderByValue 排序后,就可以使用此事件。

排序和过滤数据

您可以使用实时数据库 Query 类来检索按键、按值或按子项目的值排序的数据。您还可以对排序后的结果进行过滤,从而得到特定数量的结果,或者键或值在某个范围内的结果。

将数据排序

要检索经过排序的数据,请先指定一项排序依据方法,确定如何对结果排序:

方法 用法
OrderByChild() 按指定子键的值对结果排序。
OrderByKey() 按子键对结果排序。
OrderByValue() 按子值对结果排序。

您每次只能使用一种排序依据方法。在同一查询中多次调用排序依据方法会引发错误。

以下示例演示了如何接收按得分排序的得分排行榜信息。

      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
    }

此示例定义了一个查询,如果将该查询与一个 valuechanged 事件侦听器结合使用,就能使客户端数据与数据库中的排行榜同步,并按每个条目的得分进行排序。如需详细了解如何高效地设计您的数据结构,请参阅设计数据库的数据结构

调用 OrderByChild() 方法可指定对结果排序所依据的子键。在此示例中,系统将按每个子项目中 "score" 子键对应的值对结果排序。如需详细了解如何对其他数据类型进行排序,请参阅如何对查询数据进行排序

过滤数据

要过滤数据,您可以在构建查询时将某种限制方法或范围方法与排序依据方法结合使用。

方法 用法
LimitToFirst() 设置要返回的最大项目数:从经过排序的结果列表开头算起。
LimitToLast() 设置要返回的最大项目数:从经过排序的结果列表结尾算起。
StartAt() 返回大于或等于指定键或值的项目,具体取决于所选的排序依据方法。
EndAt() 返回小于或等于指定键或值的项目,具体取决于所选的排序依据方法。
EqualTo() 返回等于指定键或值的项目,具体取决于所选的排序依据方法。

与排序依据方法不同,您可以结合使用多种限制或范围函数。例如,您可以结合使用 StartAt()EndAt() 方法将结果限制在指定的取值范围内。

即使查询仅存在一个匹配项时,该快照仍是一个仅包含单个项目的列表。

限制结果数量

您可以使用 LimitToFirst()LimitToLast() 方法来设置当运行给定回调函数时要同步的子项目数上限。例如,如果您使用 LimitToFirst() 将数量上限设为 100,则一开始最多只会收到 100 次 ChildAdded 事件。如果您的 Firebase 数据库中存储的项目少于 100 个,则每个项目都会触发一次 ChildAdded 事件。

随着项目发生更改,对于新进入查询结果集的项目,您将收到 ChildAdded 事件;对于不再属于查询结果集的项目,您将收到 ChildRemoved 事件,而总数始终保持为 100。

例如,以下代码将返回排行榜中的最高分:

      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
    }

按键或值过滤

您可以使用 StartAt()EndAt()EqualTo() 为查询选择任意起始点、结束点和等值点。这对于将数据分页或查找其子节点具有特定值的项目非常有用。

如何对查询数据进行排序

本部分将介绍如何通过 Query 类中的每种排序依据方法对数据进行排序。

OrderByChild

使用 OrderByChild() 时,系统会按如下方式对包含指定子键的数据进行排序:

  1. 指定子键的值为 null 的子项目排在最前面。
  2. 接下来是指定子键的值为 false 的子项目。如果多个子项目的值均为 false,则按照键以字典顺序对它们进行排序。
  3. 接下来是指定子键为 true 值的子项目。如果多个子项目的值均为 true,则按键以字典顺序对它们进行排序。
  4. 接下来是值为数字的子项目,按升序排序。如果指定子节点的多个子项目具有相同的数字值,则按键对它们进行排序。
  5. 字符串显示在数字后面并按字典顺序以升序排列。如果指定子节点的多个子项目具有相同的值,则按键以字典顺序对它们进行排序。
  6. 指定子键值为对象的子项目放在最后,并按照键以字典顺序排列(升序)。

OrderByKey

当使用 OrderByKey() 对数据进行排序时,系统会按照键以升序返回数据。

  1. 键可以解析为二进制 32 位整数的子项目排在最前,按升序排列。
  2. 以字符串值作为键的子项目排在后面,按字典顺序以升序排列。

OrderByValue

使用 OrderByValue() 时,系统将按子项目本身的值对其进行排序。排序标准与 OrderByChild() 中相同,但这里使用的是节点本身的值而非指定子键的值。

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面