13

I have a name of the song, with ratings I am saving for it. And it looks like pic bellow, as I am using push() to store each new rating.

data example

But what I would like to see is, ratings as an array of objects, each containing something like this:

voter: {
    ip: "1.1.1.1",
    stars: 3,
}

So rating key would end up being something like this:

rating: [{ip: "1.1.1.1", stars: 3}, ...]

Then I can enable only one vote per IP address. What I couldn't find in Firebase docs, is how to add to an existing key, in this case rating(but it would be [list, like]) - a new hash like the one above. Because push() automatically creates hash-key value, and I want to append to an existing key.

EDIT: I am aware of the fact, that Firebase does not store arrays natively, however in this case it does not matter, it's just how I would like to see my data.

branquito
  • 3,864
  • 5
  • 35
  • 60

3 Answers3

15

You are currently using push to add new children, which automatically generates a name for the new node that is "guaranteed" to be unique across multiple clients.

ref.push({ ip: userIP, stars: userStars });

Firebase's push method is a great way to have multiple clients adding items to an ordered collection. If you want to accomplish the same using arrays, you'd have to synchronize the length of the array between the clients. Firebase's name generation doesn't require such overhead, so is normally the preferred of keeping an order collection across multiple clients.

But in your case, you don't seem to want an ordered "append only" collection. It seems like you consider the IP address to be an identification of each node. In that case I would use the IP address as the basis for the node name:

votes
  "1.1.1.1": 3
  "1.2.3.4": 5
  "1.7.4.7": 2

You would accomplish this with:

ref.child(userIP).set(userStars);

If you want to subsequently read all votes into an array, you can do:

var votes = [];
votesRef.on('value', function(snapshot) {
    snapshot.forEach(function(vote) {
        votes.push({ ip: vote.key, stars: vote.val() });
    });
    alert('There are '+votes.length+' votes');
})
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
0

I wanted to create a reusable function to add/save any object under a root node (even if that has an array of data at any level within the object). So I came up with this. (I am not sure if conforms to the best practices, but it worked pretty smooth)

    SaveWholeData: function(sKey, oVal, bGenKey) {
        bGenKey = bGenKey === undefined ? true: bGenKey;
        var oOriginalProperty = angular.copy(oVal);
        for (var property in oVal) {
            if (oVal.hasOwnProperty(property) && oVal[property] instanceof Array) {
                console.log(property);
                oVal[property] = "$|$";
            }
        }
        var sOwnRef = SaveDataByKey(sKey, oVal, bGenKey);
        for (var property in oVal) {
            if (oVal.hasOwnProperty(property) && oVal[property] === "$|$") {
                oVal[property] = oOriginalProperty[property];
                var updatedReference = sOwnRef + "/" + property;
               SaveWholeData(updatedReference, oVal[property], false);
            }
        }
        return true;
    },
    SaveDataByKey: function(sKey, oVal, bGenKey) {
        if (bGenKey) {
            var newPostKey = firebase.database().ref(sKey).push().key;
            oVal.genKey = newPostKey;
            firebase.database().ref(sKey).child(newPostKey).set(oVal);
            return sKey + "/" + newPostKey;
        }else{
            firebase.database().ref(sKey).set(oVal);
            return sKey;
        }
    }

So to add new user under root users, you call:

SaveWholeData("users", oUserInfo, true);

and to update existing user:

SaveWholeData("users"+"/"+ oUserInfo.genKey, oUserInfo, true);
Mahesh
  • 3,727
  • 1
  • 39
  • 49
0

After get the values from database firebase, you can storege it in another array using forEach(), like so:

 const arrayPlayers = []
        this.db.database.ref('player').once('value')
           .then((snapshot)=> {               
                snapshot.forEach((childSnapShot:any)=>{
                    arrayPlayers.push(childSnapShot.val())
                })
                //Here your array will be withut the node, like so:
                //[3,5,1,...]
                //Now sort array with JS
                const sortPlayers = arrayPlayers.sort((a:any, b:any)=> b.score - a.score)
                console.log(sortPlayers);

            })