Firebase in Swift nested query not working properly

后端 未结 2 712
梦谈多话
梦谈多话 2020-12-18 10:00

I have a JSON structure like the following:

{
  \"groups\" : {
    \"-KAv867tzVgIghmr15CM\" : {
      \"author\" : \"ruben\",
      \"name\" : \"Item A\"
            


        
相关标签:
2条回答
  • 2020-12-18 10:17

    Phew, that took some time to write. Mostly because I don't iOS/Swift a lot:

    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)
                }
            })
        }
    })
    

    By the way, this is how you create a minimal, complete verifiable example. The code has no external dependencies (such as Group and DataService in your code) and only contains what's relevant to the answer.

    The important bits:

    • I used observeSingleEventOfType to get each group, since I don't want to get more callbacks if a group changes
    • I use snapshot.childSnapshotForPath("name").exists() to check if your group has a name. You probably want to either ensure they all have names or add them to the list with some other property in the real app.
    0 讨论(0)
  • 2020-12-18 10:22

    Frank's answer is on-point. I wanted to throw in an alternative that may or may not work for your situation as it requires a slight alteration to the database.

    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
    

    And then some ObjC Code for a Deep Query

    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);
    }];
    

    This code does a deep query on the /groups for all groups that have a /users/uid_0 = true. In this case it returns gid_0 and gid_2

    It eliminates the need for iterations and multiple calls to the database.

    Adding a /users/ node to each group with a list of the uid's may offer some additional flexibility.

    Just a thought.

    0 讨论(0)
提交回复
热议问题