【问题标题】:Delete all documents in Firestore collection删除 Firestore 集合中的所有文档
【发布时间】:2020-09-08 23:06:18
【问题描述】:

我制作了一个按钮,应该让用户根据他们的用户 ID 删除所有数据,该按钮与“删除您的帐户”按钮具有相同的目的,但它不起作用。我尝试使用以下代码删除集合中的所有文档:

final String userid = FirebaseAuth.getInstance.getCurrentUser().getUid();

        db.collection("main").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
            @Override
            public void onComplete(@NonNull Task<QuerySnapshot> task) {
                for (QueryDocumentSnapshot queryDocumentSnapshot : task.getResult()){
                    db.collection("main").document(userid).delete();
                }
            }
        })

有一个runtimeExecution:没有权限错误

    com.google.android.gms.tasks.RuntimeExecutionException: com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions.

我将安全规则设置如下,以使其他用户无法访问其他用户的数据。

service cloud.firestore {
  match /databases/{database}/documents {
    match /main/{userId}/{document=**} {
      allow read, write: if request.auth.uid == userId;
    }
  }
}

不知道该怎么办,我认为安全规则可以防止安全问题,但我认为它导致了这个权限错误?

提前谢谢你。

【问题讨论】:

    标签: android google-cloud-firestore


    【解决方案1】:

    此查询试图获取名为“main”的集合中的所有文档:

    db.collection("main").get()
    

    您的安全规则不允许这样做。这些规则只允许用户在 main 中读写自己的文档。

    目前尚不清楚您要删除的具体内容,但如果只是 main 下的用户文档,则根本不需要查询。只需这样做:

    db.collection("main").document(userid).delete();
    

    【讨论】:

    • 我正在尝试获取“主”集合下的所有用户文档并将它们全部删除,您能说明如何操作吗?
    • 您的安全规则不允许这样做。就算写了代码也行不通。
    【解决方案2】:

    如果您想访问主集合下的所有文档,您应该将您的 Firebase 规则更改为

    service cloud.firestore {
        match /databases/{database}/documents {
          match /{document=**} {
           allow read, write: if true;
        }
      }
    }
    

    虽然如果您只想删除您在代码中所做的单个用户数据:-

    db.collection("main").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
            @Override
            public void onComplete(@NonNull Task<QuerySnapshot> task) {
                for (QueryDocumentSnapshot queryDocumentSnapshot : task.getResult()){
                    db.collection("main").document(userid).delete();
                }
            }
        })
    

    你不应该纠正整个查询,你可以简单地使用删除用户文档

    db.collection("main").document(userid).delete();
    

    【讨论】:

    • 谢谢,我只是担心“允许读,写:如果为真;”会导致安全问题,因为我只想让特定用户访问他们自己的数据,有没有办法解决这个问题?
    • 是的。如果您想确保用户只能读取和写入自己的数据,那么您的规则将与您的规则相同,您只需使用 db.collection("main").document(userid).delete(); 删除用户详细信息
    【解决方案3】:

    没有 API 可以一次性删除整个集合(或其内容)。

    来自 Firestore 文档: https://firebase.google.com/docs/firestore/manage-data/delete-data

    “要删除 Cloud Firestore 中的整个集合或子集合,请检索集合或子集合中的所有文档并将其删除。如果您有较大的集合,您可能希望以较小的批量删除文档以避免超出-内存错误。重复此过程,直到删除整个集合或子集合。"

    【讨论】:

      【解决方案4】:

      更新:

      在做了一些研究并阅读了这个网站上关于这个问题的许多其他答案之后,我使用了这种方法,我认为对于像我这样的傻瓜来说它是如此简单,但从未在其他答案中提及我不知道为什么:

      为了从身份验证中完全删除用户,我使用了名为“删除用户数据”的 Firestore 扩展程序,这是一个很大的帮助,它很神奇,让我只需使用以下代码即可删除用户:

      FirebaseAuth.getInstance().getCurrentUser().delete().addOnSuccessListener(new OnSuccessListener<Void>() {...}
      

      它不仅删除了用户身份验证,仅使用该代码,firestore 中特定用户的数据和存储中的图像也消失了。太棒了! 重要的一点是,您必须从身份验证连接用户 UID,并将 UID 连接到 Firestore 和存储。

      要了解有关如何使用“删除用户数据”Firestore 扩展程序的更多信息(它仍处于测试模式),请尝试查看 JORGE VERGARA 的这篇很棒的博客教程:Installing the Delete User Data extension

      我如何设置扩展的配置来删除用户:

      如何使用扩展程序:它是如此简单我很高兴它可以帮助我轻松删除用户而无需大惊小怪

      这是存储结构:

      我的 Firestore 的结构:

      main(collection)--->userID---->journal(collection)----->journalIDdsvsfbsf
                                                        ----->journalIDdfvdbgnd
                      --->userID2--->journal(collection)----->journalIDdsvsfbsf
                                                        ----->journalIDdfvdbgnd
      

      身份验证结构:

      了解 Firestore 和存储必须如何使用相同的用户 UID 连接,以便 Firestore 扩展可以通过删除身份验证轻松删除用户。

      如果您仍想使用旧方法: 我注意到您不能仅使用 delete 方法删除包含一个或多个子集合的 Firestore 文档。例如,如果您要删除包含 3 个子集合的文档,为了删除该文档(在我的情况下为用户),您必须获取其中一个子集合中的所有文档,将它们全部删除,然后继续对该文档中的所有其他子集合执行相同的操作。一旦删除了文档中的所有子集合,则包含它们的文档将自行消失。这就是 Firestore 的工作方式。

      将其放入代码中: 删除包含子集合“journal”的文档 如果不使用扩展,我必须这样做:

      FirebaseFirestore.getInstance().collection("main").document(userid).collection("journal").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                      @Override
                      public void onComplete(@NonNull Task<QuerySnapshot> task) {
                          if (task.isSuccessful()) {
                              for (final QueryDocumentSnapshot document : task.getResult()) {
                                  if (document.exists()){
                                      db.collection("main").document(userid).collection("journal").document(document.getId()).delete().addOnSuccessListener(new OnSuccessListener<Void>() {
                                          @Override
                                          public void onSuccess(Void aVoid) {
      
                                          }
                                      }).addOnFailureListener(new OnFailureListener() {
                                          @Override
                                          public void onFailure(@NonNull Exception e) {
                                              Toast.makeText(SettingsActivity.this, "Journal: " + e.getMessage(), Toast.LENGTH_LONG).show();
                                          }
                                      });
                                  } else {
                                      Toast.makeText(SettingsActivity.this, "No data in JOURNAL", Toast.LENGTH_SHORT).show();
                                  }
                              }
                          } else {
                              Toast.makeText(SettingsActivity.this, "Journal task: " + task.getException(), Toast.LENGTH_LONG).show();
                          }
                      }
                  }).addOnFailureListener(new OnFailureListener() {
                      @Override
                      public void onFailure(@NonNull Exception e) {
                          Toast.makeText(SettingsActivity.this, "Error getting all the documents: " + e.getMessage(), Toast.LENGTH_LONG).show();
                      }
                  });
      

      如果您在该特定文档中有多个子集合,要删除它,您必须为不同的子集合重复该代码多次,这会使代码很长。

      我希望这对试图从 Firestore 中删除用户的人有所帮助。 :) 已经在使用扩展了。

      【讨论】:

        猜你喜欢
        • 2018-11-01
        • 2018-10-19
        • 2023-03-24
        • 1970-01-01
        • 2018-03-22
        • 2020-09-17
        • 2020-01-03
        相关资源
        最近更新 更多