Android构建Firebase Firestore上传结构及数据覆写问题求助
解决Firestore覆写数据与数组存储的问题
问题根源分析
你当前的代码用set()方法写入数据,这个方法的特性是:如果目标文档已经存在,会直接替换整个文档的内容,这就是为什么之前的数据会被覆写。另外,Firestore其实是支持ArrayList的,只是你当前的结构没有正确使用数组来存储多个NewVendor对象。
解决方案一:用数组字段追加新对象(适合少量数据)
这种方式会在你的用户文档里维护一个vendors数组,每次添加新供应商时用FieldValue.arrayUnion()来追加元素,不会覆写原有数据。
步骤1:调整数据类
首先确保你的NewVendor类有无参构造函数(Firestore序列化/反序列化必须):
public class NewVendor { public String title; public Map<String,String> array; // 必须添加无参构造函数,Firestore需要它来反序列化 public NewVendor() {} public NewVendor(String title, Map<String, String> array) { this.title = title; this.array = array; } }
步骤2:用update()+arrayUnion()添加新对象
替换原来的set()方法,改用update()并结合FieldValue.arrayUnion()来追加新供应商:
Map<String,String> list = new HashMap<>(); list.put("Vendor Name", newVendorName); list.put("Vendor Address", newVendorAddress); NewVendor newVendor = new NewVendor(newVendorName, list); db.collection("Bills").document(firebaseUser.getUid()) .update("vendors", FieldValue.arrayUnion(newVendor)) .addOnSuccessListener(aVoid -> { Toast.makeText(AddNewBillActivity.this, "Success", Toast.LENGTH_SHORT).show(); }) .addOnFailureListener(e -> { Toast.makeText(AddNewBillActivity.this, "Failure: " + e.getMessage(), Toast.LENGTH_SHORT).show(); });
注意:如果文档还不存在,
update()会失败,你可以先检查文档是否存在,或者用set()配合SetOptions.merge()来初始化:db.collection("Bills").document(firebaseUser.getUid()) .set(new HashMap<String, Object>(){{put("vendors", new ArrayList<>());}}, SetOptions.merge()) .addOnSuccessListener(...)
解决方案二:用子集合存储(适合大量数据)
如果你的供应商数量较多,或者需要单独查询/修改某个供应商,推荐用子集合来存储每个NewVendor对象,这种方式更灵活,也不会有数组大小的限制:
Map<String,String> list = new HashMap<>(); list.put("Vendor Name", newVendorName); list.put("Vendor Address", newVendorAddress); NewVendor newVendor = new NewVendor(newVendorName, list); // 在用户的Bills文档下创建Vendors子集合,添加新文档(自动生成唯一ID) db.collection("Bills").document(firebaseUser.getUid()) .collection("Vendors") .add(newVendor) .addOnSuccessListener(documentReference -> { Toast.makeText(AddNewBillActivity.this, "Success! Vendor ID: " + documentReference.getId(), Toast.LENGTH_SHORT).show(); }) .addOnFailureListener(e -> { Toast.makeText(AddNewBillActivity.this, "Failure: " + e.getMessage(), Toast.LENGTH_SHORT).show(); });
这种方式下,每个供应商都是子集合里的独立文档,不会互相覆盖,还能方便地查询单个供应商、分页加载等。
关键知识点总结
set()方法默认会替换整个文档,要避免覆写可以用update()或者SetOptions.merge()。FieldValue.arrayUnion()可以安全地向数组字段追加元素,不会重复添加内容完全一致的对象。- Firestore完全支持
ArrayList,只要你的数据类提供无参构造函数,且字段是public或者有对应的getter/setter。
内容的提问来源于stack exchange,提问作者Lakshya Punhani
相关产品推荐
相关产品推荐

