2016-05-29 10 views
11

Nella seguente guida di Firebase a structuring data per un'app di chat. Suggeriscono la struttura come visto di seguito.Strutturazione dei dati per l'app di chat in Firebase

{ 
    // Chats contains only meta info about each conversation 
    // stored under the chats's unique ID 
    "chats": { 
    "one": { 
     "title": "Historical Tech Pioneers", 
     "lastMessage": "ghopper: Relay malfunction found. Cause: moth.", 
     "timestamp": 1459361875666 
    }, 
    "two": { ... }, 
    "three": { ... } 
    }, 

    // Conversation members are easily accessible 
    // and stored by chat conversation ID 
    "members": { 
    // we'll talk about indices like this below 
    "one": { 
     "ghopper": true, 
     "alovelace": true, 
     "eclarke": true 
    }, 
    "two": { ... }, 
    "three": { ... } 
    }, 

    // Messages are separate from data we may want to iterate quickly 
    // but still easily paginated and queried, and organized by chat 
    // converation ID 
    "messages": { 
    "one": { 
     "m1": { 
     "name": "eclarke", 
     "message": "The relay seems to be malfunctioning.", 
     "timestamp": 1459361875337 
     }, 
     "m2": { ... }, 
     "m3": { ... } 
    }, 
    "two": { ... }, 
    "three": { ... } 
    } 
} 

Come faccio a strutturare i miei dati utente in modo che possa facilmente visualizzare un elenco di tutte le chat di cui fanno parte e per ognuno di essi visualizzare l'ultimo messaggio e timestamp. Se faccio la seguente struttura:

"users": { 
    "ghopper": { 
     "name": "Gary Hopper", 
     "chats": { 
      "one: true", 
      "two": true 
     } 
    }, 
    "alovelace" { ... } 
    }, 

posso facilmente ottenere un elenco di ogni gruppo chat per un utente specifico, ad esempio ghopper, facendo (in rapido):

ref.child("users").child("ghopper").child("chats").observeSingleEventOfType(.Value, withBlock: { (snapshot) in 
    //do something with data 
} 

Tuttavia ho vinto avere l'ultimo messaggio e il timestamp in questa istantanea. Cosa devo fare per accedere a questi dati?

  • Duplicare tutti questi dati per ciascun utente? cioè aggiungendo utenti/ghopper/chat/uno/{"lastMessage": "ghopper: malfunzionamento del relay trovato Causa: falena", "timestamp": 1459361875666}
  • Effettua una query per "chat/specificGroupId" per ogni chat che l'utente fa parte di (aggiungere più listener)?
  • In qualche altro modo?

risposta

2

Nel blocco in cui si dispone di un elenco di tutte le chat un utente è in, si può fare:

var dictionary: [String: Long] 
var lastMessage: String 
for chat in listOfChatsUserIsIn 
    ref.child("chats").child("\(chat)").child("lastMessage").observeSingleEventOfType(.Value, withBlock: { (snapshot) in 
     lastMessage = snapshot 
     ref.child("chats").child("\(chat)").child("timestamp").observeSingleEventOfType(.Value, withBlock: { (snapshot) in 
      //add timestamp and last message to dictionary 
     } 
    } 

Non so come corretta la mia sintassi è. Sto ancora imparando Firebase. Ma, penso che questo sia fondamentalmente il tuo secondo suggerimento. Non so in quale altro modo otterresti i dati. Questo sarebbe O (2n) anche se non è male.

[[Update 1]]

Ero essere pigro con il mio codice. Ho inserito lastMessage = snapshot per salvarlo in modo da poterlo aggiungere al dizionario nel blocco successivo.

Per quanto riguarda Firebase è asincrono. Penso che funzionerebbe ancora finché si utilizza il timestamp o il messaggio come chiave e l'altro come valore nel dizionario. Può essere popolato fuori servizio, ma è sempre possibile ordinarlo per data e ora. Sebbene, sì, questa probabilmente non è la migliore pratica.

Jay, mi piace la tua soluzione. Non dovresti anche elencare uid_2: false?

Sfortunatamente, sembra che entrambe queste strutture di database crescano di n^2 come utenti -> inf e come chat -> inf.

+0

Qual è la funzione di lastMesssage = snapshot poiché non si utilizza tale variabile? Inoltre, è buona norma usare il nome self.variable all'interno di un blocco (chiusura). Inoltre, il file di ricerca all'interno del primo ref.child è un duplicato, quindi leggerà gli stessi dati. Il problema più grande è che Firebase è asincrono e che il ciclo for tight sta per essere eseguito * way * più velocemente di quanto i dati possano essere restituiti all'interno del blocco observ, quindi penso che si verifichino problemi di integrità dei dati - probabilmente Firebase dovrebbe farlo è 'roba' in modo asincrono. – Jay

+0

Per rispondere alla domanda nella risposta. No, uid_2: false non è necessario come se non esistesse, potrebbe essere falso di default (dipende dal suo codice). E no, il database non cresce esponenzialmente. Se hai 10 utenti e 1 chat, tutti e 10 gli utenti sono in quella chat quindi l'unica cosa che cresce sarebbe il nodo degli utenti all'interno della chat (nella mia risposta) allo stesso modo se hai 1000 utenti e 100 chat, ogni chat con due utenti , sono ancora solo 100 chat ciascuna con un nodo utenti con due utenti. Anche con 1000 utenti e 1000 chat, questa non è una quantità notevole di dati. – Jay

17

Come faccio a strutturare i miei dati utente in modo che possa facilmente visualizzare un elenco di tutte le chat di cui fanno parte e per ognuno di essi visualizzare l'ultima messaggio e timestamp.

Modificare la struttura chat un po 'dagli utenti aggiungendo che si trovano nel nodo Chat

"chats": { 
    "one": { 
     "title": "Historical Tech Pioneers", 
     "lastMessage": "ghopper: Relay malfunction found. Cause: moth.", 
     "timestamp": 1459361875666 
     users 
     uid_1: true 
     uid_3: true 
    }, 
    "two": { ... }, 

Poi si può interrogare in profondità per tutte le chat di un particolare utente è parte di - Ciò restituirà la chat uid_3 è coinvolti in

chatsRef.queryOrderedByChild("users/uid_3").queryEqualToValue(true) 
    .observeSingleEventOfType(.Value, withBlock: { snapshot in 

    //.Value can return multiple nodes within the snapshot so iterate over them 
    for child in snapshot.children { 
      let lastmsg = child.value["lastMessage"] as! String 
      let timestamp = child.value["timestamp"] as! String 
      print(lastmsg) 
      print(timestamp) 
    }  
}) 

noti che ogni utente Firebase ha un id utente discreto ottenuto quando l'utente viene creato tramite auth.uid. Questo dovrebbe (generalmente) essere usato come chiave per ogni utente.

+1

Ciao Jay, grazie per la tua risposta. Ho provato la tua soluzione e sembra che faccia il trucco. Ma questa operazione non diventerà troppo costosa quando avrò molti utenti, considerando che dovrei cercare tra tutte le "chat /" per trovare tutte le chat di cui l'utente fa parte? – Nilsymbol

+1

@Nilsymbol Contento che ha funzionato! Non sembra che tu stia tirando giù megabyte di dati, solo poche centinaia di nodi con alcuni bambini. Firebase è incredibilmente veloce, quindi fare una query come questa su migliaia di nodi è super veloce; non farà nemmeno respirare il respiro di Firebase. L'abbiamo provato! – Jay

+0

@Jay Capisco la struttura per la maggior parte, semplicemente non capisco come gli utenti sono rappresentati nei bambini "chat". È un array di utenti uid? Potresti spiegare un po 'di più l'associazione di Boolean con l'uid? Grazie mille! -Colbey – justColbs