Swift嵌套查询中的Firebase无法正常工作

我有一个像这样的JSON结构:

{ "groups" : { "-KAv867tzVgIghmr15CM" : { "author" : "ruben", "name" : "Item A" }, "-KAv87nqLEG1Jtc04Ebn" : { "author" : "ruben", "name" : "Item B" }, "-KAv88yZe8KTfkjAE7In" : { "author" : "ruben", "name" : "Item C" } }, "users" : { "rsenov : { "avatar" : "guest", "email" : "ruben@ruben.com", "groups" : { "-KAv867tzVgIghmr15CM" : "true", "-KAv87nqLEG1Jtc04Ebn" : "true", "-KAv88yZe8KTfkjAE7In" : "true" } } } } 

每个用户都有一个带有childByAutoId()键的元素“groups”。 然后我有应用程序中存在的所有组的列表。

每次我运行应用程序,我得到当前用户login的url参考,我得到该用户的组列表(在这种情况下,login的用户是“rsenov”有3个组)。 对于这个用户所属的每个组,我遍历组url参考,寻找获得这三个组的信息。

我这样做是这样的:

 func loadTable() { self.groups = [] var counter = 0 self.meses = [] var tempItems = [String]() DataService.dataService.CURRENT_USER_GROUPS_REF.observeEventType(.Value, withBlock: { snapshot in if let snapshots = snapshot.children.allObjects as? [FDataSnapshot] { tempItems = [] for snap in snapshots { DataService.dataService.GROUPS_REF.childByAppendingPath(snap.key).queryOrderedByChild("name").observeEventType(.Value, withBlock: { snapshot in if let postDictionary = snapshot.value as? Dictionary<String, AnyObject> { tempItems.append(snapshot.value.objectForKey("name") as! String) let key = snapshot.key let group = Group(key: key, dictionary: postDictionary) self.groups.insert(group, atIndex: 0) } counter++ if (counter == snapshots.count) { self.meses = tempItems self.miTabla.reloadData() } }) } } }) } 

我认为这样做并不是一个好主意。 例如,如果GROUPS_REF url中的某个子节点发生更改,则代码只运行在该嵌套代码中,并且由于它没有从for循环获取的“snap.key”值,所以它不起作用。

在这种情况下,做好查询的最好方法是什么?

唷,这花了一些时间来写。 主要是因为我没有iOS / Swift很多:

 let ref = Firebase(url: "https://stackoverflow.firebaseio.com/35514497") let CURRENT_USER_GROUPS_REF = ref.childByAppendingPath("users/rsenov/groups") let GROUPS_REF = ref.childByAppendingPath("groups") var counter: UInt = 0 var groupNames = [String]() CURRENT_USER_GROUPS_REF.observeEventType(.Value, withBlock: { groupKeys in for groupKey in groupKeys.children { print("Loading group \(groupKey.key)") GROUPS_REF.childByAppendingPath(groupKey.key).observeSingleEventOfType(.Value, withBlock: { snapshot in print(snapshot.value) if (snapshot.childSnapshotForPath("name").exists()) { groupNames.append(snapshot.value.objectForKey("name") as! String) } counter++ if (counter == groupKeys.childrenCount) { print(groupNames) } }) } }) 

顺便说一句,这是你如何创build一个最小的,完整的可validation的例子 。 代码没有外部依赖性(例如代码中的GroupDataService ),只包含与答案相关的内容。

重要的一点:

  • 我使用observeSingleEventOfType来获取每个组,因为如果组发生更改,我不想获得更多的callback
  • 我使用snapshot.childSnapshotForPath("name").exists()来检查你的组是否有名字。 你可能想要确保他们都有名字,或者把他们添加到真正的应用程序中的其他属性列表。

弗兰克的回答是点。 我想抛出一个替代scheme,可能会或可能不适合您的情况,因为它需要对数据库稍作修改。

 groups gid_0 author: "ruben" name: "Item A" users uid_0: true gid_1 author: "ruben" name: "Item B" users uid_1: true gid_2 author: "ruben" name: "Item C" users uid_0: true 

然后一些深查询的ObjC代码

 Firebase *ref = [self.myRootRef childByAppendingPath:@"groups"]; FQuery *query1 = [ref queryOrderedByChild:@"users/uid_0"]; FQuery *query2 = [query1 queryEqualToValue:@"true"]; [query2 observeSingleEventOfType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) { NSLog(@"key: %@ value: %@", snapshot.key, snapshot.value); }]; 

此代码对所有具有/ users / uid_0 = true的组执行深层查询。 在这种情况下,它返回gid_0和gid_2

它消除了迭代和多次调用数据库的需要。

使用uid列表将/ users /节点添加到每个组可能会提供一些额外的灵活性。

只是一个想法。