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

Android Studio Java中如何在Firestore两集合保存同ID文档数据

在Firebase Firestore中向两个集合存储相同文档ID的数据

我希望在Firebase Firestore的两个不同集合中存储具有相同文档ID的数据。我尝试了一段代码但无法理解其逻辑,以下是我尝试的代码:

FirebaseFirestore firestore = FirebaseFirestore.getInstance();
// Get the document from the first collection
DocumentReference sourceDocumentRef = firestore.collection("collection1").document("documentId");
sourceDocumentRef.get().addOnSuccessListener(documentSnapshot -> {
    if (documentSnapshot.exists()) {
        // Create a new document in the second collection with the same data
        firestore.collection("collection2").document("documentId").set(documentSnapshot.getData())
                .addOnSuccessListener(aVoid -> {
                    // Document successfully copied
                })
                .addOnFailureListener(e -> {
                    // Error copying document
                });
    } else {
        // Document does not exist in the first collection
    }
})
.addOnFailureListener(e -> {
    // Error retrieving document
});

这是我项目中的简化代码:

db.collection("measurements")
.document(RoundTxt)
.set(measurementData)
.addOnSuccessListener(new OnSuccessListener() {
    @Override
    public void onSuccess(Void unused) {
        Toast.makeText(getActivity(), "Measurement Added ", Toast.LENGTH_SHORT).show();
        Navigation.findNavController(view).navigate(R.id.action_newUserTab_to_oldUserTab);
    }
})
.addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        Toast.makeText(getActivity(), "Failed to Added Measurement", Toast.LENGTH_SHORT).show();
    }
});

代码逻辑解析

你尝试的第一段代码是**"读取-复制"**逻辑:

  1. 先从collection1读取指定ID的文档
  2. 读取成功且文档存在时,把该文档的数据写入collection2的同ID文档
  3. 分别处理读取、写入环节的异常情况

但你的项目代码是主动写入新数据,不需要先读再写,直接同时向两个集合写入相同数据即可,这样更高效。

优化方案:直接并行写入两个集合

可以同时发起两个写入请求,用Tasks.whenAll等待所有操作完成后统一处理结果:

FirebaseFirestore db = FirebaseFirestore.getInstance();
String docId = RoundTxt; // 相同的文档ID

// 向第一个集合写入
Task<Void> task1 = db.collection("measurements")
        .document(docId)
        .set(measurementData);

// 向第二个集合写入(示例集合名可根据实际修改)
Task<Void> task2 = db.collection("measurements_backup")
        .document(docId)
        .set(measurementData);

// 等待两个任务完成
Tasks.whenAll(task1, task2)
        .addOnSuccessListener(aVoid -> {
            Toast.makeText(getActivity(), "Measurement added to both collections", Toast.LENGTH_SHORT).show();
            Navigation.findNavController(view).navigate(R.id.action_newUserTab_to_oldUserTab);
        })
        .addOnFailureListener(e -> {
            Toast.makeText(getActivity(), "Failed to add measurement: " + e.getMessage(), Toast.LENGTH_SHORT).show();
        });

关键说明

  • 这种方式避免了额外的读操作,直接复用measurementData写入两个集合,性能更优
  • Tasks.whenAll会等待两个写入操作都完成才触发成功回调,只要其中一个失败就会进入失败回调
  • 如果需要保证原子性(要么两个都成功,要么都失败),Firestore原生不支持跨集合事务,但可以考虑:
    1. 使用云函数触发写入(当第一个集合写入成功后,自动写入第二个集合)
    2. 把两个集合的写入放在同一个事务中(注意Firestore事务单批次最多处理500个文档,且必须是同一个数据库)

内容的提问来源于stack exchange,提问作者Bhadra Vaghela

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 23:23:06