You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:34:33