We may use Transaction when using Firebase Realtime Database. I think most of its use is a case of operating continuous values.
Since there are many restrictions on Transaction, I thought that it was better to solve with Server's Queue System.
We propose to extend ServerValue there.
Increment the number saved in the Firebase Realtime Database.
If the value is not saved, set it to 1
ServerValue.increment(Value)
Decrement the number saved in Firebase Realtime Database.
ServerValue.decrement(Value)
or Calcurate
ServerValue.calcurate(Value)
In Firebase it is necessary to use Transaction when operating Increment.
Save data as transactions
Transaction will lock a node.
When updating multiple data simultaneously on different nodes, performance will be degraded because it is necessary to lock at the upper node.
Also, as the amount of data increases, it is necessary to transfer a large amount of snapshots.
__Before__
ref.runTransactionBlock({ (currentData: MutableData) -> TransactionResult in
if var post = currentData.value as? [String : AnyObject], let uid = Auth.auth().currentUser?.uid {
var stars: Dictionary<String, Bool>
stars = post["stars"] as? [String : Bool] ?? [:]
var starCount = post["starCount"] as? Int ?? 0
if let _ = stars[uid] {
// Unstar the post and remove self from stars
starCount -= 1
stars.removeValue(forKey: uid)
} else {
// Star the post and add self to stars
starCount += 1
stars[uid] = true
}
post["starCount"] = starCount as AnyObject?
post["stars"] = stars as AnyObject?
// Set value and report transaction success
currentData.value = post
return TransactionResult.success(withValue: currentData)
}
return TransactionResult.success(withValue: currentData)
}) { (error, committed, snapshot) in
if let error = error {
print(error.localizedDescription)
}
}
__After__
let userID: String = Auth.auth().currentUser!.uid
let values: [AnyHashable: Any] = [
"/user/stars/\(userID)": true,
"/user/starCount": ServerValue.increment(1)
]
Database.database().reference().updateChildValues(values) { (error, ref) in
if let error = error {
print(error.localizedDescription)
}
}
Although I can not do it only by changing the client, I would like you to introduce it
We are planning to add this as a feature to Firestore, but are not intending to backport this feature to the RTDB.
Most helpful comment
We are planning to add this as a feature to Firestore, but are not intending to backport this feature to the RTDB.