在我的数据库中递增一个int值,我首先通过监听器获取该值,将其加1,然后将新值设置为数据库。这种方法可行,但我想知道是否有更简单的方法。这种方式似乎太麻烦了。
在我的数据库中递增一个int值,我首先通过监听器获取该值,将其加1,然后将新值设置为数据库。这种方法可行,但我想知道是否有更简单的方法。这种方式似乎太麻烦了。
更新:自2020年初以来,实际上已经有一种服务器端操作可以增加实时数据库中的值。请参阅dfeverx在此问题上的答案,或者我的Q&A比较事务和递增之间的性能:您可以多快地对Firebase实时数据库中的值进行原子递增?。
Firebase数据库没有服务器端增加值(或执行其他计算)的方法。
您的方法是一种实现递增的方式,但可能会导致竞争条件。
结果现在可能不正确(这取决于您的用例)。
在这种情况下,一种使其正常工作的方法是使用Firebase事务,将读取和写入组合成单个函数。
事务在Firebase数据库文档中有详细介绍。强烈建议阅读它。花费几个小时在那里将避免未来很多问题。从文档中可以了解到:
postRef.runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
Long value = mutableData.getValue(Long.class);
if (value == null) {
mutableData.setValue(0);
}
else {
mutableData.setValue(value + 1);
}
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot) {
Log.d(TAG, "transaction:onComplete:" + databaseError);
}
});
从Firebase JavaScript SDK v7.14.0开始,您可以使用ServerValue.increment()
在Firebase中增加值。
方法1
var userRef= firebase.database().ref("user/user_id_123");
userRef.push({
likes: firebase.database.ServerValue.increment(1)
});
方法二
firebase.database()
.ref('user')
.child('user_id_123')
.child('likes')
.set(firebase.database.ServerValue.increment(1))
您还可以将浮点数或负值传递给增量函数。
您可以在这里找到参考链接:https://firebase.google.com/docs/reference/js/v8/firebase.database.ServerValue
Kotlin 版本:
val ref = Firebase.database.reference
.child("users")
.child(postId)
.child("likes")
ref.runTransaction(object : Transaction.Handler {
override fun doTransaction(mutableData: MutableData): Transaction.Result {
val value = mutableData.getValue(Long::class.java)
if (value == null) {
mutableData.value = 0
} else {
mutableData.value = value + 1 // to decrement - mutableData.value = value - 1
}
return Transaction.success(mutableData)
}
override fun onComplete(error: DatabaseError?, committed: Boolean, currentData: DataSnapshot?) {
if (error != null) {
println("transaction-onCompleteError: ${error.message}")
}
val currentCount = currentData?.getValue(Long::class.java) ?: 0L
println("currentCount: $currentCount")
}
})