2016-04-29 33 views
11

Voglio ottenere un elenco di elementi in Firebase, ma ogni elemento dell'elemento ha un elenco di elementi correlati. Non sono stato in grado di ottenere l'elenco, né utilizzando firebase-util né la funzionalità $extend dell'array Firebase.Recupera un elenco di elementi correlati di un elenco di elementi in un array di basi

miei dati Firebase simile a questa:

items 
    item1 
     name: "Item 1" 
     user: user1 
     images 
      image1: true 
      image2: true 
    item2 
     name: "Item 2" 
     user: user1 
     images: 
      image3: true 
      image4: true 
    item3 
     name: "Item 3" 
     user: user2 
     images: 
      image5: true 
      image6: true 

users 
    user1 
     name: "User 1" 
     email: "[email protected]" 
    user2 
     name: "User 2" 
     email: "[email protected]" 

images 
    image1 
     image: "data:image/jpeg;base64,/9j/..." 
     thumb: "data:image/jpeg;base64,/9j/..." 
    image2 
     image: "data:image/jpeg;base64,/9j/..." 
     thumb: "data:image/jpeg;base64,/9j/..." 
    image3 
     image: "data:image/jpeg;base64,/9j/..." 
     thumb: "data:image/jpeg;base64,/9j/..." 
    image4 
     image: "data:image/jpeg;base64,/9j/..." 
     thumb: "data:image/jpeg;base64,/9j/..." 
    image5 
     image: "data:image/jpeg;base64,/9j/..." 
     thumb: "data:image/jpeg;base64,/9j/..." 

e voglio solo per ottenere un elenco di elementi con tutti i dati. Qualcosa di simile:

items 
    item1 
     name: "Item 1" 
     user 
      name: "User 1" 
      email: "[email protected]" 
     images 
      image1 
       image: "data:image/jpeg;base64,/9j/..." 
       thumb: "data:image/jpeg;base64,/9j/..." 
      image2 
       image: "data:image/jpeg;base64,/9j/..." 
       thumb: "data:image/jpeg;base64,/9j/..." 
    item2 
     name: "Item 2" 
     user 
      name: "User 1" 
      email: "[email protected]" 
     images 
      image3 
       image: "data:image/jpeg;base64,/9j/..." 
       thumb: "data:image/jpeg;base64,/9j/..." 
      image4 
       image: "data:image/jpeg;base64,/9j/..." 
       thumb: "data:image/jpeg;base64,/9j/..." 
    item3 
     name: "Item 3" 
     user 
      name: "User 2" 
      email: "[email protected]" 
     images 
      image5 
       image: "data:image/jpeg;base64,/9j/..." 
       thumb: "data:image/jpeg;base64,/9j/..." 
      image6 
       image: "data:image/jpeg;base64,/9j/..." 
       thumb: "data:image/jpeg;base64,/9j/..." 

Sembra un caso d'uso abbastanza comune, ma sono bloccato qui. Ho provato la soluzione this (in entrambi i modi) ma non ho potuto farlo funzionare. Anche la struttura dei dati è leggermente diversa poiché ho bisogno di mettere in relazione una lista che si trova all'interno di un'altra lista.

+0

Così com'è, non è possibile recuperare i dati nel formato che stai chiedendo, sulla base di struttura attuale. Puoi fornire informazioni sul motivo per cui desideri ottenere TUTTI questi dati contemporaneamente? Normalmente otterresti un elenco di nomi utente o un elenco di immagini che vanno con l'Articolo 3 ma di solito non tutte in una volta. Penso che ci possa essere una soluzione alla tua domanda e la comprensione del caso d'uso ti aiuterà. – Jay

+0

@Jay Voglio mostrare un elenco di articoli. Ogni elemento ha una lista di immagini, ma mostrerò solo una di esse nella lista come immagine principale dell'articolo. E perché no, forse al passaggio del mouse vorrei passare a un altro. Ma almeno se potessi farlo solo con uno sarebbe bello. – cor

risposta

2

Grazie a @Jay e @Eric per le risposte, che sono stati molto utili, la mia soluzione ha un po 'di entrambi. Spiegherò come l'ho capito.

In primo luogo, ho modificato lo schema e aggiunto una nuova chiave per l'immagine principale dell'articolo. L'ho chiamato cover. Ma rispondendo alla domanda originale, lo farò caricando tutte le immagini. Così qui è il nuovo items schema:

items 
    item1 
     name: "Item 1" 
     user: user1 
     cover: image1 
     images 
      image1: true 
      image2: true 
    item2 
     name: "Item 2" 
     user: user1 
     cover: image3 
     images: 
      image3: true 
      image4: true 
    item3 
     name: "Item 3" 
     user: user2 
     cover: image5 
     images: 
      image5: true 
      image6: true 

allora, questo è come ottenere la lista di cui sopra (usando async biblioteca). Può essere un approccio migliore per ottenere la stessa:

getItems: function(cb){ 
    var items = ref.child("items"); 
    items.on("value", function(snapshot){ 

     var item_length = snapshot.numChildren(), 
      final_items = [], 
      readed = 0; 

     ref.child("items").on("child_added", function(item){ 

      var item_id = item.key(), 
       itemData = item.val(), 

       user = ref.child("users").child(itemData.user), 
       cover = ref.child("images").child(itemData.cover), 
       images = new Firebase.util.NormalizedCollection(
         [ref.child("items").child(item_id).child("images"),'alertImages'], 
         ref.child('images') 
       ).select('images.image','images.thumb').ref(); 

       async.parallel([ 
        function(callback){ 
         user.on("value", function(user_snap){ 
          callback(null, user_snap.val()); 
         }); 
        }, 
        function(callback){ 
         images.on("value", function(images_snap){ 
          callback(null, images_snap.val()); 
         }); 
        }, 
        function(callback){ 
         cover.on("value", function(cover_snap){ 
          callback(null, cover_snap.val()); 
         }); 
        } 
       ], function(err, results){ 
        if(!!err){ 
         cb(err,null) 
        }else{ 
         itemData.user = results[0]; 
         itemData.images = results[1]; 
         itemData.cover = results[2]; 

         final_items.push(itemData); 
         readed += 1; 
         if(readed === item_length){ 
          cb(null,final_items); 
         } 
        } 
       }); 
     }); 
    }); 
} 

E questa uscita qualcosa vi piacerà:

item1 
    name: "Item 1" 
    cover: 
     image: "data:image/jpeg;base64,/9j/..." 
     thumb: "data:image/jpeg;base64,/9j/..." 
    user 
     name: "User 1" 
     email: "[email protected]" 
    images 
     image1 
      image: "data:image/jpeg;base64,/9j/..." 
      thumb: "data:image/jpeg;base64,/9j/..." 
     image2 
      image: "data:image/jpeg;base64,/9j/..." 
      thumb: "data:image/jpeg;base64,/9j/..." 
item2 
    name: "Item 2" 
    cover: 
     image: "data:image/jpeg;base64,/9j/..." 
     thumb: "data:image/jpeg;base64,/9j/..." 
    user 
     name: "User 1" 
     email: "[email protected]" 
    images 
     image3 
      image: "data:image/jpeg;base64,/9j/..." 
      thumb: "data:image/jpeg;base64,/9j/..." 
     image4 
      image: "data:image/jpeg;base64,/9j/..." 
      thumb: "data:image/jpeg;base64,/9j/..." 
item3 
    name: "Item 3" 
    cover: 
     image: "data:image/jpeg;base64,/9j/..." 
     thumb: "data:image/jpeg;base64,/9j/..." 
    user 
     name: "User 2" 
     email: "[email protected]" 
    images 
     image5 
      image: "data:image/jpeg;base64,/9j/..." 
      thumb: "data:image/jpeg;base64,/9j/..." 
     image6 
      image: "data:image/jpeg;base64,/9j/..." 
      thumb: "data:image/jpeg;base64,/9j/..." 
+0

Felice di avere una soluzione. Tieni d'occhio quelle chiamate asincrone all'interno di altre chiamate asincrone. Questo potrebbe metterti nei guai, quindi verificherei spesso i tuoi dati - specialmente con il push() e test su più dispositivi per leggere/scrivere dati all'incirca nello stesso momento. – Jay

+0

Grazie per il consiglio @Jay, cercavo un codice del genere nelle risposte, non solo sulla struttura del codice. Al momento non ho trovato niente di meglio. Continuerò a provare comunque – cor

4

L'obiettivo è mostrare un elenco di articoli.

Ogni articolo ha un elenco di immagini.

Inizialmente, mostra l'elenco degli articoli e una delle immagini per ciascun articolo.

approccio consigliata:

per popolare l'elenco degli elementi e delle loro anteprime iniziali, abbiamo bisogno di avere un nodo separato che ci tira la configurazione iniziale da.

elementi aggiornati nodo

items: 
    item_id_xx: //this should be a Firebase generated node name 
    name: "Item 2" 
    user: "uid_for_user_1" 
    images: 
    image3: "data:image/jpeg;base64,/9j/..." 
    image4: "data:image/jpeg;base64,/9j/..." 

Ecco il nodo utilizzato per la lista principale, dove l'utente può cliccare su un pollice voce per ottenere maggiori dettagli:

item_list_for_ui 
    random_node_0 
    item_id: "item_id_aa" 
    name: "Item 1" //if you want to display the name in the list 
    initial_thumb: "data:image/jpeg;base64,/9j/..." //initial thumb 
    link_to: "image1" 
    random_node_1 
    item_id: "item_id_xx" 
    name: "Item 2" 
    initial_thumb: "data:image/jpeg;base64,/9j/..." 
    link_to: "image3" 
    random_node_2 
    item_id: "item_id_qq" 
    name: "Item 3" 
    initial_thumb: "data:image/jpeg;base64,/9j/..." 
    link_to: "image1" 

Quando inizia app, popolare la lista dal nodo items_list_for_ui.

Il nodo è poco profondo e contiene il firebase item_id, il nome dell'elemento (se necessario), il collegamento per ottenere l'anteprima dell'immagine iniziale da e il link_to dell'immagine principale in Firebase.

Ad esempio: se l'utente fa clic sulla miniatura per la voce 2, i dettagli dell'elemento possono essere caricati da observeSingleEvent con .value a

/oggetti/item_id_xx/images/image3

Si potrebbe esporre su questo con l'aggiunta di esempio, un collegamento rollover al item_list_for_ui

random_node_1 
    item_id: "item_id_xx" 
    name: "Item 2" 
    initial_thumb: "data:image/jpeg;base64,/9j/..." 
    thumb_link: "image3" 
    rollover_thumb: "external link to rollover" 
    rollover_link: "image4" 

Questa struttura è molto flessibile in quanto è possibile cambiare ciò che pollice e rollover che si desidera visualizzare nella lista principale, semplicemente aggiornando i rispettivi nodi figlio.

È anche efficiente in quanto evita il caricamento di centinaia di elementi e centinaia di nodi immagine figlio - il caricamento di tutti quei nodi e nodi figlio sovraccaricherebbe l'interfaccia utente (in alcuni casi).

Con questa struttura, item_list_for_ui è compatto, quindi anche con centinaia di elementi, è un piccolo sottoinsieme di tali dati.

Probabilmente stai dicendo a te stesso "sono dati duplicati".Sì, lo è, e la duplicazione dei dati in Firebase è un processo normale e incoraggiato: mantiene la struttura più piatta e rende le query e lavora con i dati molto più velocemente.

Per ulteriori lettura vedere Denormalizing Data Keeps Your Breath Minty Fresh

+0

Grazie per la risposta @ Jay. Ma come vorresti unirti ai dati? useresti il ​​plugin 'firebase-util'? Se é cosi, come? Non so come fare la relazione dato che l'ID dell'articolo è dinamico – cor

+0

@cor Firebase non ha una funzione di join in quanto non è SQL. Esistono diversi modi per associare i dati e la duplicazione dei dati è accettabile in Firebase. Penso che la mia risposta abbia risposto alla tua domanda diretta. Il tuo commento/follow up è una grande nuova domanda (e ci sono alcune risposte che lo riguardano già su Stackoverflow). Dai un'occhiata a quelle risposte e se hai una domanda specifica, pubblicala! – Jay

+0

scusa, hai ragione – cor

2

Se si dispone di tutti i dati disponibili si potrebbe scorrere le immagini e utilizzare i metadati come chiavi all'interno del resto del database.

var itemsArr = []; 
    for(var i in items) { 
     var item = items[i]; 
     var images = []; 
     for(var image in item[images]) { 
      item.push(images[image]); 
     } 
     itemsArr.push({ 
      name: item.name, 
      user: users[item.user], 
      images: images 
     }); 
    } 

Quale dovrebbe produrre un array di oggetti che cercano in questo modo:

{ 
    name: "Item 1", 
    user: { 
     name: "User 1", 
     email: "[email protected]" 
    }, 
    images: [{ 
      image: "data:image/jpeg;base64,/9j/..." 
      thumb: "data:image/jpeg;base64,/9j/..." 
     },{ 
      image: "data:image/jpeg;base64,/9j/..." 
      thumb: "data:image/jpeg;base64,/9j/..." 
    }] 
} 
+0

Molte grazie @Eric N, la tua risposta è stata utile per ciò che volevo raggiungere – cor

Problemi correlati