javascriptangularjsfirebaseangularfirefirebase-util

Retrieve a related item list of an item list in a firebase array


I want to get a list of items in firebase, but each element of the item has a list of related items. I haven't been able to get the list, neither using firebase-util nor firebase array $extend functionality.

My firebase data looks something like this:

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: "user1@email.com"
    user2
        name: "User 2"
        email: "user2@email.com"

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/..."

And I just want to get a list of items with all the data. Something like:

items
    item1
        name: "Item 1"
        user
            name: "User 1"
            email: "user1@email.com"
        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: "user1@email.com"
        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: "user2@email.com"
        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/..."

It looks like a fairly common use case, but I'm stucked here. I have tried this solution (in both ways) but I couldn't get it work. The data structure is also a bit different since I need to relate a list which is inside another list.


Solution

  • Thanks to @Jay and @Eric for the answers, they have been very helpful, my solution has a bit of both. I will explain how have I figured it out.

    Firstly, I have changed the schema and added a new key for the item's main picture. I have called it cover. But answering the original question, I will do it loading all the images. So here is the new 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
    

    Then, this is how I get the list mentioned above (using async library). It may be a better approach to accomplish the same:

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

    And this will output something like:

    item1
        name: "Item 1"
        cover:
            image: "data:image/jpeg;base64,/9j/..."
            thumb: "data:image/jpeg;base64,/9j/..."
        user
            name: "User 1"
            email: "user1@email.com"
        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: "user1@email.com"
        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: "user2@email.com"
        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/..."