1

Ich arbeite an einer Gruppenchatanwendung und es treten Probleme auf, wenn versucht wird, eine bestimmte Abfrage an die Firebase-DB zu senden.Ermitteln eines bestimmten untergeordneten Werts von Knoten, in denen die UID des Benutzers vorhanden ist

Ich brauche alle Profilbilder von Benutzern in einem Raum zu bekommen. Aber nur die Räume, in denen der jetzige Benutzer ist.

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

Offensichtlich Einstellung queryEqual(toValue: nil) kehrt alle Zimmer, die der aktuelle Benutzer nicht ein Teil ist - das Gegenteil von dem, was ich brauche. Ich weiß, dass die Umkehrung sein wird, queryEqual(toValue: true) zu überprüfen, aber die : true wird nicht in der Datenbank angezeigt.

Dies ist, wie ich einen Knoten zu „Gruppen“ in Firebase hinzu:

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

Und dies ist, wie die Datenstruktur endet:

"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" 
    }, 

Wie kann ich richtig die profilePicture Werte für alle Benutzer in einem Raum, nur für die Gruppen, an denen die UID des aktuellen Benutzers teilnimmt?

Antwort

1

Sie sind auf dem richtigen Weg. Wenn Sie queryEqual verwenden, muss Ihre Abfrage mit dem tatsächlich in der Datenbank vorhandenen Wert übereinstimmen. Leider wird das kompliziert, wenn die Werte, gegen die Sie suchen, komplexe Objekte sind. In der Tat bin ich nicht sicher, ob die Funktion auch funktioniert, wenn Sie den gesamten Objektwert übereinstimmen. Das Problem hier ist, dass Sie versuchen, Objekte durch das Vorhandensein eines untergeordneten Schlüssels nachschlagen, anstatt nach ihren Werten tatsächlich zu sortieren oder zu vergleichen. Das passt nicht ganz zum Anwendungsfall irgendeiner der orderBy Methoden.

Es gibt ein paar Möglichkeiten, um dies zu umgehen, geordnet nach Aufwand.

Erste, könnten Sie die Vorteile der sort order nehmen nur diejenigen, die mit dem Namen des UID etwas bezwecken zu erhalten. Da Firebase zuerst Nullen, dann Primitive und schließlich Objekte sortiert, sollten Sie in der Lage sein, nach Kind und beitrue (oder einem beliebigen Primitiv) zu sortieren, um alle Objektinstanzen mit diesem Schlüssel zu erhalten (vorausgesetzt, Sie sind es natürlich nicht) Speichern UID: true überall).

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

Zweite, duplizieren Sie die UID als Schlüssel innerhalb des Objekts mit dem Wert true, so dass Sie auf sie direkt sortieren. Beachten Sie den zusätzlichen Schritt in der Abfrage.

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

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

Schließlich, und das ist, was ich empfehlen, Ihre Datenstruktur überdenken. Sie verschachteln viele Daten in dieser Sammlung von Sammlungen, wodurch Ihre Abfragen und Aktualisierungen unhandlich werden. Firebase neigt dazu, besser zu arbeiten, wenn Sie denormalize your data bevorzugen flache/flache Strukturen mit einigen Doppelung von einfachen Daten.Wenn Sie in Ihrem Fall die Profildaten des Benutzers nicht innerhalb ihrer Gruppenmitgliedschaft speichern, verfügen Sie möglicherweise über eine Sammlung von Gruppen und eine andere Sammlung von Benutzern, wobei jede Gruppe nur eine Liste von UIDs für ihre Mitglieder enthält. und umgekehrt. Das Beispiel in der Dokumentation ist ein sehr ähnlicher Fall wie bei Ihnen, bei dem Sie an Chat-Unterhaltungen teilnehmen. An diesem Punkt haben Ihre UIDs (und Gruppen-IDs, wenn Sie stattdessen Benutzer abfragen) den Wert true, so dass Sie wieder eine einfache Wertabfrage verwenden können.

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

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

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

+0

Gute Antwort, Dank werde ich diese Vorschläge versuchen. Ich habe 3 "Parent" Knoten in Firebase: 1. Benutzer (hauptsächlich für die Suche nach Benutzern von Handle verwendet) 2. Rooms (hält die Nachrichten jedes Raumes) und 3. Gruppen (identisch mit Räumen, außer mit Teilnehmerdaten und minus die Nachrichten) . Ich wundere mich aber, ich setze den Gruppenknoten mit '" Teilnehmern ": [uid: true]' ... wieso zeigt es sich in Firebase nicht so? Ich setze den Raumknoten auf die gleiche Weise und das ': true' erscheint dort. Einziger Unterschied ist, dass der Raumknoten keine Benutzerdaten enthält. – KingTim

+0

Ich müsste mehr von Ihrem Code sehen, um eine klare Antwort zu geben, aber aus Ihren Beispielen sieht es so aus, als ob Sie den ursprünglichen "wahren" Wert mit den Benutzerprofildaten irgendwann überschreiben müssen. Ein Knoten kann nicht sowohl einen Wert als auch Kinder speichern. Das klingt nach einer möglicherweise separaten Frage. –

Verwandte Themen