We know that Firebase does not have a request for counting, there are two methods to get a counter, get all the data on the client side or save the count value in the database. I use this second method because the first only works when there is more than one data.
The problem with this method is that I can have many parallel authors, I solved this problem with my method, so that if the data is not stored, it tries to re-save the data using an incremented or reduced counter.
OK, this method worked well when I want to change only one counter, but in different cases I want to change many different counters with one transaction, and in this mode there is a risk that after various attempts, the data cannot be saved, because we have there can be many concurrent authors in many different sites. An example data structure with atomic updates is shown below:
If I keep this
"comment": {
"counter": {},
"Data": {
"$Comment":{}
}
}
comment/counter = val + 1
comment/Data/comment1 = data
it works if I do not update, because another writer only updates the counter when I can try again with a new counter value, and usually after the first time I complete the operation with success, but, for example, if I want to delete the user and all of it actions, I want to save this type of data
"comment":{
"counter":{},
"Data": {
"$Comment":{}
}
},
"$user": {
"follower":{
"counter":{},
"data":{
"$Follower": {}
}
}
}
comment/counter = val - 1
comment/Data/comment2 = null
user1/follower/counter = val - 1
user1/follower/data/user30 = null
user2/follower/counter = val - 1
user2/follower/data/user30 = null
user3/follower/counter = val - 1
user3/follower/data/user30 = null
, , , , .
-
"photo":{
"$photo":{
"comment":{
"counter":{},
"Data": {
"$Comment":{}
}
}
}
photo/10/comment/counter = val - 1
photo/10/comment/Data/comment1 = null
photo/10/comment/counter = val - 1
photo/10/comment/Data/comment2 = null
photo/10/comment/counter = val - 1
photo/10/comment/Data/comment3 = null
, , + 1 - 1. , , , , .
, , (sql nosql). , . , .
javascript . , , -
this.singleUpdate = function (paths, increment, countPath, retryCounter, callback) {
firebase.database().ref(countPath).once('value', function (counter) {
var value = counter.val() ? counter.val().value : 0;
var countValue = increment ? value + 1 : value - 1;
paths[countPath] = { value: null };
if (!increment && countValue == 0) { paths[countPath] = null; }
else {
paths[countPath].value = countValue;
}
firebase.database().ref().update(paths, function (error) {
if (error) {
retryCounter++;
if (retryCounter < 3) { singleUpdate(paths, increment, countPath, retryCounter, callback); }
else { callback(false, error); }
} else {
return callback(true, countValue);
}
});
});
}