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(); } });
代码逻辑解析
你尝试的第一段代码是**"读取-复制"**逻辑:
- 先从
collection1读取指定ID的文档 - 读取成功且文档存在时,把该文档的数据写入
collection2的同ID文档 - 分别处理读取、写入环节的异常情况
但你的项目代码是主动写入新数据,不需要先读再写,直接同时向两个集合写入相同数据即可,这样更高效。
优化方案:直接并行写入两个集合
可以同时发起两个写入请求,用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原生不支持跨集合事务,但可以考虑:
- 使用云函数触发写入(当第一个集合写入成功后,自动写入第二个集合)
- 把两个集合的写入放在同一个事务中(注意Firestore事务单批次最多处理500个文档,且必须是同一个数据库)
内容的提问来源于stack exchange,提问作者Bhadra Vaghela
相关产品推荐
相关产品推荐

