Android Firebase安全规则在多路径更新期间失败

Android Firebase安全规则在多路径更新期间失败,android,firebase,firebase-realtime-database,firebase-security,Android,Firebase,Firebase Realtime Database,Firebase Security,在firebase中,我设置了安全规则以保护一些节点 问题 当我使用multi-path update同时更新多个路径时,如果一个安全规则对多个路径中的任何一个失败,那么整个更新都会失败 我的问题示例 假设我的实时数据库中有3个节点(用户、人员、任务),在android中,一起更新这3个路径的方法如下: Map multi-update =new HashMap(); multi-update.put("users/user1/name","any_name"); m

在firebase中,我设置了安全规则以保护一些节点

问题

当我使用multi-path update同时更新多个路径时,如果一个安全规则对多个路径中的任何一个失败,那么整个更新都会失败

我的问题示例

假设我的实时数据库中有3个节点(用户、人员、任务),在android中,一起更新这3个路径的方法如下:

     Map multi-update =new HashMap();

    multi-update.put("users/user1/name","any_name");
    multi-update.put("people/user2/status", "any_status");
    multi-update.put("tasks/task1/details", "any_details");

    DatabaseReference root=FirebaseDatabase.getInstance().getReference();

    //update
     root.updateChildren(multi-update);
    "users":{
       ".write":"true"
     }

    ,"people":{
        ".write":"true"
      }
    ,"tasks":{
        ".write":"false"
        } 
root.updateChildren(multi-update, new DatabaseReference.CompletionListener() {
    @Override
    public void onComplete(DatabaseError firebaseError, DatabaseReference firebase) {
        if (firebaseError != null)
        {
            //Update the minimum required fields
        }
    }
});
假设我的规则是这样的:

     Map multi-update =new HashMap();

    multi-update.put("users/user1/name","any_name");
    multi-update.put("people/user2/status", "any_status");
    multi-update.put("tasks/task1/details", "any_details");

    DatabaseReference root=FirebaseDatabase.getInstance().getReference();

    //update
     root.updateChildren(multi-update);
    "users":{
       ".write":"true"
     }

    ,"people":{
        ".write":"true"
      }
    ,"tasks":{
        ".write":"false"
        } 
root.updateChildren(multi-update, new DatabaseReference.CompletionListener() {
    @Override
    public void onComplete(DatabaseError firebaseError, DatabaseReference firebase) {
        if (firebaseError != null)
        {
            //Update the minimum required fields
        }
    }
});
因为任务不允许写入,所以在所有路径都允许写入之前,多路径更新永远不会更新

有人能解释为什么会这样吗

谢谢。

根据:

以这种方式进行的同步更新是原子性的:要么是所有更新 成功或所有更新失败

因此,您描述的问题实际上不是问题,而是
root.updateChildren(multi-update)的预期行为

如果这种行为在您的案例中是一个问题,您可以更改firebase规则以授予多重更新的所有部分的权限,或者将多重更新拆分为多个部分,以确保能够成功的部分将成功

在您的情况下,另一个选项是检查以下错误:

     Map multi-update =new HashMap();

    multi-update.put("users/user1/name","any_name");
    multi-update.put("people/user2/status", "any_status");
    multi-update.put("tasks/task1/details", "any_details");

    DatabaseReference root=FirebaseDatabase.getInstance().getReference();

    //update
     root.updateChildren(multi-update);
    "users":{
       ".write":"true"
     }

    ,"people":{
        ".write":"true"
      }
    ,"tasks":{
        ".write":"false"
        } 
root.updateChildren(multi-update, new DatabaseReference.CompletionListener() {
    @Override
    public void onComplete(DatabaseError firebaseError, DatabaseReference firebase) {
        if (firebaseError != null)
        {
            //Update the minimum required fields
        }
    }
});

缺点是您不知道更新的哪一部分失败。

但有时由于某些限制,一条或多条规则需要失败,一些节点应该与单个更新一起保存。在这种情况下,我们应该怎么做?假设B通过原子写入同时写入A和B节点,然后假设某一天A决定阻止或解除B的好友关系。然后,当B执行原子写入时,由于安全规则,它不会在A节点中更新,也不会在B节点中更新。那么我们该怎么办?@svi.data我在回答中添加了另一个选项,也许这就是你想要的?我想避免在回拨中添加代码,但无论如何还是要感谢你的帮助。这种行为是出于设计:只有在所有更改成功的情况下才会提交多位置更新。如果您想单独提交写操作,请对每个写操作单独调用
updateChildren
。@FrankvanPuffelen如果我单独对每个3个节点调用update,它仍然是多路径更新吗?不是,但这只是定义问题。您不希望进行多路径更新,因为您希望每个更新单独成功。在这一点上,这听起来很像一个问题:通过执行这三个更新,你想实现什么?@FrankvanPuffelen我希望写入操作能够进入数据库,而不必相互依赖(我不想将它们链接在一起,因为当连接断开时,onComplete回调不会持久化)。当我发送它们时(在线或离线),我希望始终确保它们一起发送。如果您不希望原子写入,则作为单个数据包发送的附加优势可以忽略不计。但不管怎样:您将需要进行单独的调用,因为无法以您想要的方式使用单个多位置更新。