Can I prevent Firebase set() from overwriting existing data?

13,476

Solution 1

The Firebase update() function will allow you to modify some children of an object while leaving others unchanged. The update function will only trigger one "value" event on other clients for the path being written no matter how many children are changed.

In this example, you could do:

itemRef.update({appreciates:newFlag,id:newId});

Documentation for update() is here.

Solution 2

You can create a rule that will prevent overwrites if data already exists. Reproduced here from Firebase docs Existing Data vs New Data

// we can write as long as old data or new data does not exist
// in other words, if this is a delete or a create, but not an update
".write": "!data.exists() || !newData.exists()"

Solution 3

Now .update takes care of it, you can change existing data or add new one without affecting the rest of data you already had there.

In this example, I use this function to set a product as sold, the product has other variables with data and may or may not have sold or sellingTime but it doesn't matter cos if it doesn't exist will create them and if it does, will update the data

var sellingProduct = function(id){
 dataBase.ref('product/'+id).update({
   sold:true,
   sellingTime: Date.now(),

 }).then (function(){
   alert ('your product is flaged as sold')

 }).catch(function(error){
    alert ('problem while flaging to sold '+ error)
 })

}

Solution 4

Though you can use update, you can also use set with merge option set to true:

itemRef.set({ appreciates:newFlag, id:newId }, { merge: true });

This will create a new document if it doesn't exists and update the existing if it does.

Solution 5

I've been trying to do this having a structure like the following:

Firebase gigs database structure

The problem I was having was when running say set on specific fields such as name, description and date all of the other child nodes would then be removed with the following:

return (dispatch) => {
    firebase.database().ref(`/gigs/${uid}`)
        .set({ name, description, date })
        .then(() => {
            dispatch({ type: GIG_SAVE_SUCCESS });
            Actions.home({ type: 'reset' });
        });
};

Leaving only the name, description and date nodes but using the following the specific nodes are updated without removing the other child nodes i.e. members, image etc:

return (dispatch) => {
    var ref = firebase.database().ref(`/gigs/${uid}`);
    ref.child('name').set(name)
    ref.child('description').set(description)
    ref.child('date').set(date)
        .then(() => {
            dispatch({ type: GIG_SAVE_SUCCESS });
            Actions.home({ type: 'reset' });
        });
}; 
Share:
13,476
Itumac
Author by

Itumac

I am a seasoned user experience professional specializing in the human element of web development. I blend cross-functional talents in Behavior Design, Interaction Design and Front-end Technology to make complex web and mobile applications that are engaging, simple and fun to use.

Updated on June 16, 2022

Comments

  • Itumac
    Itumac about 2 years

    If I do this, all is good with my itemRef:

    itemRef.child('appreciates').set(newFlag);
    itemRef.child('id').set(newId);
    

    other properties of itemRef remain BUT child_changed is called twice

    If I do this:

    itemRef.set({appreciates:newFlag,id:newId});
    

    child_changed is called only once but my other properties are destroyed. Is there a workaround besides the clumsy one of repopulating the entire reference object?

    Thanks,

    Tim