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

时间:2016-02-19 20:34:39

标签: ios json 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"
      }
    }
  }
}

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

每次运行应用程序时,我都会获得当前用户记录的url引用,并获得该用户组的列表(在这种情况下,登录用户是" rsenov"那有3组)。 对于该用户所属的每个组,我遍历组url引用,寻找获取该3个组的信息。

我是这样做的:

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中的某个子项发生了更改,则代码只会在该嵌套代码中运行,并且因为它没有&#34; snap.key&#34;从for循环得到的值,它不起作用。

在这种情况下,哪种方法可以做出更好的查询?

2 个答案:

答案 0 :(得分:2)

Phew,花了一些时间写。主要是因为我没有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)
            }
        })
    }
})

顺便说一句,这就是你创建minimal, complete verifiable example的方法。代码没有外部依赖项(例如代码中的GroupDataService),只包含与答案相关的内容。

重点:

  • 我使用observeSingleEventOfType来获取每个组,因为如果组更改,我不想获得更多回调
  • 我使用snapshot.childSnapshotForPath("name").exists()检查您的论坛是否有名称。您可能希望确保它们都具有名称,或者将它们添加到列表中,并在真实应用程序中添加其他属性。

答案 1 :(得分:2)

弗兰克的回答是正确的。我想提出一个可能适用于您的情况的替代方案,因为它需要对数据库稍作修改。

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的所有组的/ groups进行深层查询。在这种情况下,它返回gid_0和gid_2

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

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

只是一个想法。