Update Firebase Multi-Location with Error: Path Is an Ancestor of Path. Swift

Firebase: How do I update multiple resources atomically?

UPDATE

It's now possible to update multiple locations atomically. See this blog post for details.

var mergedUpdate = {};
mergedUpdate[ 'users/' + userId + '/widgets/' + widgetId ] = true;
mergedUpdate[ 'widgets/' + widgetId ] = widgetData;

var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");
ref.update(mergedUpdate);

This doesn't enforce transactional data (if value is currently X, make it Y), but this part can be moved to security rules. For example, if we want to update two counters at the same time, we could add rules as follows:

{
"counter1": {
".validate": "newData.val() === (data.val()||0)+1"
},

"counter2"1 {
".validate": "newData.val() === (data.val()||0)+1"
}
}

Now we can attempt the same multi-path update as above. If the values have changed since we last read them from the server, the attempt will fail. We can check if( error.code === 'PERMISSION_DENIED' ) { ... } to see if the failure was due to validation, and retry accordingly.

ORIGINAL POST

The only way to do this is to run a transaction on a common ancestor.

For instance, if you want to update /a/b/c and /a/x/y, you could run a transaction at /a and change both of the values.

The downside to this approach is that it can be expensive with network I/O, as all of the data inside the transaction needs to be downloaded and then sent back to the server.

A more complicated but potentially more powerful approach you might want to consider is restructuring your data so that rather than storing the actual values, you store a history of the edits. For example, if you're storing bank balance information, you could store a history of deposits and withdrawals. Then when you wanted to get the balance, you would play back the whole history and calculate the end balance.

The beauty of this approach is it lets you do atomic updates. For example, if you were transferring money from accountA to accountB, you'd just append an element to the end of the log saying "transfer from account A to accountB N dollars". Appending that single element is an atomic operation.

This is the approach we take with Firepad, our collaborative text editor.

Flutter Firebase Realtime Database write/update to multiple nodes at once

What you are looking for is known as a multi-path write operation, which allows you to write to multiple, non-overlapping paths with a single update call. You can specify the entire path to update for each key, and the database will then set the value you specify at that specific path.

To generate two separate unique keys, you can call push() twice without any arguments. When called like that, it doesn't actually write to the database, but merely generates a unique reference client-side, that you can then get the key from.

Combined, it would look something like this:

const db = _firebaseDatabase.reference();
const key1 = db.push().key;
const key2 = db.push().key;
const values = {};
values["user_data/"+key1+"/username"] = "aaa";
values["user_history/"+key2+"/username"] = "aaa";
db.update(values);


Related Topics



Leave a reply



Submit