2017-05-14 3 views
0

Ich beginne gerade mit der Firebase-Datenbank und habe einige Probleme, um Daten effizient abzufragen. Meine aktuelle Datenbankstruktur ist ähnlich die Firebase Dokumentation empfohlenen Datenstrukturen, in denen wir dieses Beispiel sehen:Firebase-Datenbank für mehrere Schlüssel abfragen

// An index to track Ada's memberships 
{ 
    "users": { 
    "alovelace": { 
     "name": "Ada Lovelace", 
     // Index Ada's groups in her profile 
     "groups": { 
     // the value here doesn't matter, just that the key exists 
     "techpioneers": true, 
     "womentechmakers": true 
     } 
    }, 
    ... 
    }, 
    "groups": { 
    "techpioneers": { 
     "name": "Historical Tech Pioneers", 
     "members": { 
     "alovelace": true, 
     "ghopper": true, 
     "eclarke": true 
     } 
    }, 
    ... 
    } 
} 

Das Problem, das ich habe ist, dass ich nicht sicher bin, wie effizient alle Gruppennamen abrufen für einen bestimmten Benutzer. Ich kann leicht für einen Benutzer alle der Gruppen-IDs abrufen:

usersRef.child("alovelace").child("groups").observeSingleEvent(of: .value, with: { (snapshot) in 
// code to store group IDs 
}) 

Aber jetzt ist der einzige Weg, ich glaube, kann alle Gruppennamen zu bekommen, ist ein for-Schleife durch die IDs zu machen, dann einen Anruf tätigen .observeSingleEvent damit jeder den Namen bekommt. Aber was, wenn ich eine sehr große Gruppe von Gruppen für den Benutzer habe? Im Idealfall würde ich lieber nicht so viele Datenbankanrufe machen und es nur in einem Anruf tun. Ist das mit dieser Datenstruktur möglich?

+0

Firebase ruft die Elemente über eine einzelne offene Verbindung ab, sodass der Aufwand für die Verbindung gering ist. Das Abrufen einer angemessenen Anzahl von Elementen auf diese Weise (auch als clientseitige Verknüpfung bezeichnet) ist nicht so langsam, wie Sie vielleicht denken, da die Anforderungen über die bestehende Verbindung weitergeleitet werden. Siehe http://stackoverflow.com/questions/35931526/speed-up-fetching-posts-for-my-social-network-app-by-using-query-instead-of-obse/35932786#35932786 –

Antwort

0

Dies ist, was ich schlage vor, Sie tun. Dies füllt das Gruppen-Array mit allen Daten innerhalb der Gruppenstruktur, zu der der Benutzer gehört.

import UIKit 
import Firebase 

class TableViewController: UITableViewController { 

    var groups = Array<Group>() 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     Group.get(userUID: "alovelace") { (groups) in 

      for uid in groups { 

       Group.get(groupUID: uid, completion: { (group) in 

        if let group = group { 

         print(group) 

         self.groups.append(group) 

        } else { 

         print("There is no group with id: \(uid)") 
        } 

        self.tableView.reloadData() 
       }) 
      } 
     } 
    } 
} 

struct Group { 

    var uid: String 

    var name: String 

    var members: Array<String> 

    init?(uid:String, dict:Dictionary<String,Any>){ 

     guard 

      let name = dict["name"] as? String, 

      let users = dict["members"] as? Dictionary<String,Bool> 

     else { 

      return nil 
     } 

     self.uid = uid 

     self.name = name 

     self.members = Array<String>() 

     for (id, _) in users { 

      self.members.append(id) 
     } 
    } 

    // Returns a Group, when given a group id. 
    static func get(groupUID:String, completion: @escaping (Group?) ->()) { 

     let ref = FIRDatabase.database().reference().child("groups").child(groupUID) 

     ref.observeSingleEvent(of: .value, with: { (snapshot) in 

      if let value = snapshot.value as? Dictionary<String,Any> { 

       if let group = Group(uid: groupUID, dict: value) { 

        completion(group) 

        return 

       } else { 

        print("Incomplete Group Data") 
       } 
      } 

      completion(nil) 
     }) 
    } 

    // Returns the group ids that a user belongs to 
    static func get(userUID:String, completion: @escaping (Array<String>) ->()) { 

     let ref = FIRDatabase.database().reference().child("users").child(userUID).child("groups") 

     ref.observeSingleEvent(of: .value, with: { (snapshot) in 

      if let value = snapshot.value as? Dictionary<String,Any> { 

       completion(value.keys.sorted()) 

       return 
      } 

      completion([]) 
     }) 
    } 
} 
0

Sie können dies tun:

usersRef.child("alovelace").child("groups").observeSingleEvent(of: .value, with: { (snapshot) in 
    let result = snapshot.children.allObjects as? [FIRDataSnapshot] 
    for child in result { 
     let groupName = child.key 
     print(groupName) 
    } 
}) 
+0

Wenn ich komme bis zu (ds1 as! FIRDataSnapshot) gibt es keinen Schlüssel. Aus meiner Sicht verweist dieser Snapshot nur auf den Pfad, den ich angegeben habe (in Benutzern), daher enthält er dort nicht den Gruppennamen. Fehle ich etwas? –

+0

Entschuldigung für die vorherige Antwort, diese sollte funktionieren ich habe es bearbeitet. –

+0

Dies gibt die Namen der Schlüssel unter "Alicace" - "Name", "Gruppen". Ich möchte den tatsächlichen Namen der Elemente unter "Gruppen" zurückgeben - in diesem Fall "Historical Tech Pioneers" –