我正在使用交易在Firestore中实现帖子喜欢和评论功能。我使用交易,因为我需要在帖子中的likes / comments子集和更新计数器中添加新字段,并且还将帖子ID添加到用户喜欢/评论的帖子集合中。
我注意到如果我离线了,我就像这样请求我的帖子一切正常:
val postDocRef = FirebaseUtil.postsColRef.document(postId)
postDocRef.get().addOnSuccessListener { doc ->
val post = doc.toObject(Post::class.java)
Timber.e(post.toString())
}
但是,如果我在事务中执行相同的操作,则抛出异常:
val postDocRef = FirebaseUtil.postsColRef.document(postId)
FirebaseUtil.firestore.runTransaction(Transaction.Function<Void> { transaction ->
val post = transaction.get(postDocRef).toObject(Post::class.java)
}
例外是:
com.google.firebase.firestore.FirebaseFirestoreException:UNAVAILABLE
为什么离线模式在交易中不起作用?是否可以在离线状态下实现此功能(在子集合中添加条目并在不同对象中更新字段)?
用continueWithTask()
调用链替换事务可能有什么缺点?
答案 0 :(得分:8)
不,这对交易来说是不可能的,因为它们本质上是网络相关的。当您使用事务时,您告诉Firestore您只能同步执行数据库操作,一个客户端接着另一个。交易对于游戏中的货币转移等内容非常有用,您需要确保不会意外地将您的写入翻倍并为用户提供太多或太少的资金。
如果您的类似计数器需要具有完美的精度,我建议使用子集合,其中每个文档包含对喜欢给定帖子的用户的引用。然后,在云功能中,您可以使用交易来计算喜欢帖子的用户数量,并确保没有错误计数。这有一个额外的好处,让你知道谁喜欢一个应该是未来证明的帖子,如果你决定添加更多相关的功能。在客户端,你可以&#34;欺骗&#34;即使您没有获得许可,也可以写信给柜台。我还没有对此进行测试,但我很确定写入会在本地成功,然后只有在您重新上线后才会失败。但这并不重要,因为云功能将同步计数器服务器端。
另一方面,如果你真的不在乎拥有超精确的计数,你正在寻找的是WriteBatch
类。这是Firestore中的新功能,非常酷。我正在撰写发布的Firestore帖子,但这里有一段摘录:
Cloud Firestore还包含一种批量写入的强大新方法
WriteBatch
课程。SharedPreferences.Editor
。它非常类似于 您可以在Android上找到WriteBatch
。您可以添加或更新WriteBatch#commit()
实例中的文档,但它们不可见 您的应用,直到您致电inline fun firestoreBatch(transaction: WriteBatch.() -> Unit): Task<Void> = FirebaseFirestore.getInstance().batch().run { transaction() commit() }
。我已经创建了标准 Kotlin改进,为您管理批量生命周期 - 感觉 免费copypasta。{{1}}