1

我工作的群聊应用程序,我遇到麻烦试图使一个特定的查询到火力地堡DB。充分利用节点特定的子值仅在用户的UID存在

我需要得到所有用户的个人资料照片在一间客房。但只有当前用户所属的房间。

private func observeRooms() { 

    let databaseRef = FIRDatabase.database().reference() 
    let groupRef = databaseRef.child("groups") 

    guard let uid = FIRAuth.auth()?.currentUser?.uid else {return} 
    let queryRef = groupRef.queryOrdered(byChild: "participants/\(uid)").queryEqual(toValue: nil) 

    queryRef.observe(.childAdded, with: { snapshot in 

     let roomDict = snapshot.value as! [String: AnyObject] 
     print("roomDict: \(roomDict)") 
     let id = snapshot.key 

     let avatar = roomDict["profilePicture"] as! String 
    }) 
} 

显然设置queryEqual(toValue: nil)返回所有房间的当前用户不是的一部分 - 的什么,我需要相反。我知道反过来会检查queryEqual(toValue: true),但: true没有显示在数据库中。

这是我在火力地堡节点添加到“组”:

 // Start group node for new room 
     let groupRef: FIRDatabaseReference = FIRDatabase.database().reference().child("groups") 
     let roomID = newRoomRef.key 
     let groupRoomRef = groupRef.child(roomID) 
     let groupDict = ["roomName" : roomName, "participants": [uid : true]] as [String : Any] 
     groupRoomRef.setValue(groupDict) 

这是数据结构是如何结束:

"groups" : { 
    "-KkGzZ7frbnXmImt0JpV" : { 
    "participants" : { 
     "tzfHgGKWLEPzPU9GvkO4XE1QKy53" : { 
     "gender" : "male", 
     "handle" : "Testing", 
     "name" : "Test User", 
     "profilePicture" : "https://graph.facebook.com/*removed*/picture?type=large&return_ssl_resources=1", 
     "status" : "F8B016" 
     } 
    }, 
    "roomName" : "Test Room" 
    }, 

我怎样才能正确地为profilePicture值一个房间中的所有用户,仅针对当前用户的UID是参与者的组?

回答

1

你在正确的轨道上。当使用queryEqual时,您的查询需要匹配数据库中实际存在的值。不幸的是,当你查询的值是复杂的对象时会变得复杂。实际上,即使匹配了整个对象值,我也不确定该函数是否可以正常工作。这里的问题是,你试图通过子键的存在来查找对象,而不是实际按照值排序或匹配它们的值。这不太适合任何orderBy方法的用例。

有几种方法来解决这个问题,通过努力订购。

首先,你可以采取sort order的优势,只得到那些谁拥有有UID的名字有些对象。由于火力地堡第一排序NULL,则原语,最后的对象,你应该能够通过儿童和开始在true(或任何原始的)命令来获取所有对象实例与该键(假设,当然,你不在任何地方存储UID: true)。

groupRef.queryOrdered(byChild: "participants/\(uid)").queryStartingAtValue(true)

,复制UID为对象内的关键与价值true这样就可以直接进行排序就可以了。注意查询中的额外步骤。

"groups" : { 
    "-KkGzZ7frbnXmImt0JpV" : { 
    "participants" : { 
     "tzfHgGKWLEPzPU9GvkO4XE1QKy53" : { 
     "tzfHgGKWLEPzPU9GvkO4XE1QKy53" : true, 
     ... 

groupRef.queryOrdered(byChild: "participants/\(uid)/\(uid)").queryEqual(toValue: true)

最后,这是我的建议,重新考虑你的数据结构。您在这个集合集合中嵌入了大量数据,这会使您的查询和更新变得笨重。当你使用denormalize your data时,Firebase往往会更好,它们更喜欢平坦/浅层结构,并且有一些重复的简单数据。在您的情况下,您可能不是将用户的配置文件数据存储在其组成员资格内,而是可能有一组用户组和另一组用户,其中每个组只包含一个UID列表,反之亦然。文档中的示例与涉及聊天对话成员身份的案例非常相似。此时,您的UID(和组ID,如果您正在查询用户)将具有值true,因此您可以再次使用简单的值查询。

"groups" : { 
"-KkGzZ7frbnXmImt0JpV" : { 
    "participants" : { 
    "tzfHgGKWLEPzPU9GvkO4XE1QKy53" : true 
    ... 

"users" : { 
"tzfHgGKWLEPzPU9GvkO4XE1QKy53" : { 
    "groups" : { 
    "-KkGzZ7frbnXmImt0JpV" : true 
    ... 

groupRef.queryOrdered(byChild: "participants/\(uid)").queryEqual(toValue: true)

+0

很好的回答,谢谢,我会尝试这些建议。我在Firebase中有3个“父”节点:1.用户(主要用于通过句柄搜索用户)2.房间(保存每个房间的消息)和3.组(与房间相同,除了参与者数据并减去消息) 。我想知道,我确实使用'“参与者”设置组节点:[uid:true]'...为什么它没有在Firebase中显示出这种方式?我以相同的方式设置房间节点,并在那里显示':true'。唯一不同的是房间节点不包含任何用户数据。 – KingTim

+0

我不得不看到更多的代码来给出明确的答案,但是从您的示例看来,您必须在某个时刻用用户配置文件数据覆盖最初的“true”值。节点不能同时存储值_and_子项。这听起来像是一个单独的问题。 –

相关问题