如何从 Firebase 获取一组对象?

Posted

技术标签:

【中文标题】如何从 Firebase 获取一组对象?【英文标题】:How to get a group of objects from Firebase? 【发布时间】:2016-05-05 14:59:22 【问题描述】:

在我的 React-Native 应用程序中,我有一组特定用户,我想从 Firebase 中提取他们的值。解决此问题的最有效方法是什么?目前我正在遍历数组并为每个数组发出一个新请求(下面的相关代码):

const usersRef = new Firebase(`$ config.FIREBASE_ROOT /users`)

for (var key in usersArray) 
     var userRef = usersRef.child(key);
     //do stuff here

但是,我觉得这不是很有效,它会向数据库发出多个请求。有没有一种方法可以在一次调用中传入数组并从 Firebase 获取这些项目?谢谢。

Firebase 数据结构:


  "items" : [ 
    "description" : "fuzzy socks",
    "type" : "toy"
  , 
    "description" : "bouncy ball",
    "type" : "toy"
  , 
    "description" : "scrabble",
    "type" : "game"
  , 
    "description" : "construction paper",
    "type" : "crafts"
   ],
 "users" : [ 
    "itemList" : [ 1, 2, 3, 4 ],
    "description" : "brown",
  , 
    "itemList" : [ 5, 6, 7 ],
    "description" : "green",
  , 
    "itemList" : [ 8, 9, 10 ],
    "description" : "blue",
  , 
    "itemList" : [ 11, 12, 13 ],
    "description" : "yellow",
   ]

简化用例:在一个用例中,我只想获取有关 2 个用户的信息(在我存储在 Firebase 中的所有用户中——假设它不仅仅是上面结构中的 4 个)。所以,我有数组importantUsers:

var importantUsers = [0, 3]

然后,我想向 Firebase 发送一个请求,该请求仅在数据库中查询与这些 userID 值关联的值(因此以某种方式将数组传递给 Firebase 以获得结果)。返回值是这样的:

0: itemList: [1,2,3,4], description: brown
3: itemList: [11,12,13], description: yellow

我一次查询多个用户的数据库(而不是为用户 0 和用户 3 创建单独的引用)的动机是不要多次调用 Firebase。有没有办法解决这个问题?

【问题讨论】:

你能发布你的 Firebase 数据结构吗?请以文字形式发布(无图片)。可以从您的 Firebase 仪表板->导出按钮获取文本。 @Jay 刚刚更新了这个。 当您说“具有价值观的特定用户的数组”时,是什么将他们定义为用户,是什么让他们变得具体以及您对什么价值感兴趣?在您的 Firebase 结构中,有一个 users 节点,然后是一个字典数组,其中包含 itemList(这是一个数组)和描述的键值对,它们都不是用户。您是否在问如何访问用户节点中的数组的特定项目列表? 啊,不,所以在我的情况下,我只关心为特定的用户子集(例如,id 为 0 和 1 的用户)提取数据。所以我有一个数组 [0,1],我只想在一个查询中获取该信息。我猜类似于 SELECT * FROM "users" WHERE user_id= (items in array)。我怎样才能得到这个结果? 去吧。因此,这种结构不会发生这种情况。首先,一般来说,数组是邪恶的。它们非常难以使用,因为您无法访问数组中的特定元素,除非您知道路径,否则查询它们充其量是具有挑战性的。第二件事是将用户 ID 存储为数值可能会出现问题。从长远来看,利用用户 uid 将使其工作得更好。最后一件事是 AND 查询在 Firebase 中不直接可用。您是否要检索 userId 为 9 的节点,在这种情况下为蓝色节点? 【参考方案1】:

所以你所追求的是一个 sql 'in' 类型的查询。在 [0,2] 中选择。从列表中选择多个用户。

您问题中的另一个挑战是您感兴趣的用户是随机的,因此您不能使用 .startAt 和 .endAt,并且用户之间没有其他关系。

Firebase 不直接支持“in”、“and”或“or”类型的查询,但有多种方法可以实现。

怎么样:标记你想要的用户,然后用一个查询,读入他们。

首先,您将从一个典型的 Firebase /users 节点开始,并添加一个“选定”子节点(最初可以省略,但我在这里将其显示为占位符)

users
 uid_0
   name: "Bud"
   selected: false
 uid_1
   name: "Henry"
   selected: false
 uid_2
   name: "Billy"
   selected: false

然后,我们需要一些随机的 uid,比如 uid_0 和 uid_2,并将它们存储在一个数组中。请记住,我们将使用 Firebase 生成的 uid,但为了简单起见,我们将使用 uid_0、uid_1 等。

只有两个用户,您可以在两个节点上分别观察SingleEventOfType,没什么大不了的。

但是,如果我们需要 100 个随机用户或 1000 个用户,则应避免执行 1000 个单独的查询或observeSingleEvent。但是,setValue 非常快(没有返回数据)所以....

获取我们的用户参考

let usersRef = myRootRef.ChildbyAppendingPath("users")

我们通过遍历数组来构建这些 ref 并将 selected 设置为 true,从而知道我们想要的 100 个用户的路径

for uid in uidArray 
  let thisUserRef = usersRef.childByAppendingPath(uid)
  let selectedRef = thisUserRef.childByAppendingPath("selected")
  selectedRef.setValue(true)

然后,您可以在 usersRef 中查询选定的 child = true 的所有用户。

一旦你有了它们,清理,迭代返回的用户并将 selected 设置为 false 或 nil

这很酷的一点是,setValue 可以非常快速地通过 100 或 1000 个用户而没有开销,将他们选择的孩子设置为 true。然后一个查询就可以返回你想要的值。

写出然后读回的逻辑似乎几乎是相反的,但我很确定这比遍历数组并生成 1000 个查询或观察者要好得多。

(Firebase 的人可以检查我的那个)

另一个想法是,如果用户说,单击列表中的其他用户,您可以在他们单击时设置 selected = true,然后在用户完成时查询这些用户。

【讨论】:

这是一个很棒的创新解决方案!非常感谢!【参考方案2】:

你可以使用来自 ReactFire 的bindAsArray or bindAsObject

var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/items");
  this.bindAsArray(ref, "items");

然后您可以根据需要循环遍历该数组/对象而无需额外查询

【讨论】:

嗯,但这不会抓取整个项目列表吗?我只想要其中的一个子集,例如具有特定 ID 的项目。有没有办法将我想要的 ID 列表传递给 Firebase,并且只获取这些特定项目的结果?

以上是关于如何从 Firebase 获取一组对象?的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 3 中包含字典的 Firebase 进程子快照

在 Flutter 中将 Firebase 数据作为 Listview 构建器获取

如何在 Firebase/Auth 上避免 UIWebView

如何从android中的firebase获取对象?

如何导出所有 Firebase 远程配置键和值?

如何从 Firebase 获取 PWA 数据