如何按图示向Firestore添加集合并解决数组元素覆盖问题?
问题描述
每次调用addsymbol()函数时,希望将Coin.Coin_Info?.symbol追加到Firestore中Users/User1文档的symbols数组里,但当前代码运行时会直接覆盖原有数组,而非追加元素。
现有代码:
fun addsymbol(){ val arrayList= arrayListOf<String>() arrayList.add(Coin.Coin_Info?.symbol!!) val postHashMap = hashMapOf<String, Any>() postHashMap.put("symbols",arrayList) Firestore.collection("Users").document("User1").set(postHashMap, SetOptions.merge()) .addOnCompleteListener { task-> if(task.isSuccessful){ System.out.println("Succes ") } }.addOnFailureListener { System.out.println( it.message.toString()) } }
解决方案
你的代码问题在于每次调用函数时都创建了一个新的ArrayList,只包含当前要添加的symbol,然后用merge()方式更新文档——这会直接替换掉Firestore里原有的symbols数组,而不是追加。
要实现数组元素的追加,有两种可靠的方式:
方式1:使用Firestore的arrayUnion原子操作(推荐)
Firestore提供了FieldValue.arrayUnion()方法,可以原子性地向数组中添加元素(自动去重,不会添加重复项),不需要先读取原有数组,效率更高。
修改后的代码:
fun addsymbol(){ val symbol = Coin.Coin_Info?.symbol ?: return // 避免空指针,提前返回 // 使用arrayUnion创建追加操作 val updateData = hashMapOf<String, Any>( "symbols" to FieldValue.arrayUnion(symbol) ) Firestore.collection("Users").document("User1") .update(updateData) .addOnCompleteListener { task-> if(task.isSuccessful){ println("添加成功") } }.addOnFailureListener { println("添加失败:${it.message}") } }
注意:如果需要允许重复元素添加,Firestore没有直接的原子追加重复项的方法,需要用方式2。
方式2:先读取现有数组,再追加后更新
如果需要支持重复元素,或者需要对原有数组做其他处理,可以先读取文档中的symbols数组,添加新元素后再写回:
fun addsymbol(){ val symbol = Coin.Coin_Info?.symbol ?: return val userDocRef = Firestore.collection("Users").document("User1") // 先读取现有文档 userDocRef.get().addOnSuccessListener { document -> if (document.exists()) { // 获取原有数组,若不存在则创建新数组 val existingSymbols = document.get("symbols") as? ArrayList<String> ?: arrayListOf() existingSymbols.add(symbol) // 更新文档 userDocRef.update("symbols", existingSymbols) .addOnSuccessListener { println("添加成功") } .addOnFailureListener { println("更新失败:${it.message}") } } else { // 文档不存在时,直接创建包含初始元素的数组 val initialSymbols = arrayListOf(symbol) userDocRef.set(hashMapOf("symbols" to initialSymbols)) .addOnSuccessListener { println("文档创建并添加元素成功") } } }.addOnFailureListener { println("读取文档失败:${it.message}") } }
关键说明
- 方式1的
arrayUnion是原子操作,适合不需要重复元素的场景,避免并发更新时的冲突。 - 方式2需要先读再写,适合需要重复元素或自定义数组逻辑的场景,但要注意并发更新的问题(如果多个操作同时读写,可能会覆盖对方的修改)。
内容的提问来源于stack exchange,提问作者oguz
相关产品推荐
相关产品推荐

