Firebase:通过每用户拷贝构建数据?数据损坏的风险?

Firebase:通过每用户拷贝构建数据?数据损坏的风险?,firebase,database-schema,angularfire,firebase-realtime-database,Firebase,Database Schema,Angularfire,Firebase Realtime Database,实现一个Android+Web(Angular)+Firebase应用程序,它具有多对多关系:用户小部件(小部件可以共享给多个用户) 考虑事项: 列出用户拥有的所有小部件 用户只能看到共享给他/她的小部件 能够看到共享给定小部件的所有用户 一个小部件可以由具有相同权限的多个用户拥有/管理(修改小部件并更改其共享对象)。类似于Google Drive对特定用户进行共享的方式 实现抓取(连接样式)的方法之一是遵循以下建议:(“通过多个侦听器连接扁平化数据”)。 然而,我对这种方法持怀疑态度,因为我发

实现一个Android+Web(Angular)+Firebase应用程序,它具有多对多关系:用户小部件(小部件可以共享给多个用户)

考虑事项:

  • 列出用户拥有的所有小部件
  • 用户只能看到共享给他/她的小部件
  • 能够看到共享给定小部件的所有用户
  • 一个小部件可以由具有相同权限的多个用户拥有/管理(修改小部件并更改其共享对象)。类似于Google Drive对特定用户进行共享的方式
  • 实现抓取(连接样式)的方法之一是遵循以下建议:(“
    通过多个侦听器连接扁平化数据”)。
    然而,我对这种方法持怀疑态度,因为我发现数据加载速度会令人担忧(至少在Android上如此)——我在另一个问题中问了这个问题

    所以,这个问题是关于另一种方法:每个用户复制一个用户拥有的所有小部件。在Firebase+Udacity教程“ShoppingList++”中使用()

    其结构如下所示:

    特别是本部分-
    用户列表

      "userLists" : {
        "abc@gmail,com" : {
          "-KBt0MDWbvXFwNvZJXTj" : {
            "listName" : "Test List 1 Rename 2",
            "owner" : "xyz@gmail,com",
            "timestampCreated" : {
              "timestamp" : 1456950573084
            },
            "timestampLastChanged" : {
              "timestamp" : 1457044229747
            },
            "timestampLastChangedReverse" : {
              "timestamp" : -1457044229747
            }
          }
        },
        "xyz@gmail,com" : {
          "-KBt0MDWbvXFwNvZJXTj" : {
            "listName" : "Test List 1 Rename 2",
            "owner" : "xyz@gmail,com",
            "timestampCreated" : {
              "timestamp" : 1456950573084
            },
            "timestampLastChanged" : {
              "timestamp" : 1457044229747
            },
            "timestampLastChangedReverse" : {
              "timestamp" : -1457044229747
            }
          },
          "-KByb0imU7hFzWTK4eoM" : {
            "listName" : "List2",
            "owner" : "xyz@gmail,com",
            "timestampCreated" : {
              "timestamp" : 1457044332539
            },
            "timestampLastChanged" : {
              "timestamp" : 1457044332539
            },
            "timestampLastChangedReverse" : {
              "timestamp" : -1457044332539
            }
          }
        }
      },
    
    如您所见,购物列表的副本
    “测试列表1重命名2”
    信息显示在两个位置(针对2个用户)

    以下是完整性的其余部分:

    {
      "ownerMappings" : {
        "-KBt0MDWbvXFwNvZJXTj" : "xyz@gmail,com",
        "-KByb0imU7hFzWTK4eoM" : "xyz@gmail,com"
      },
      "sharedWith" : {
        "-KBt0MDWbvXFwNvZJXTj" : {
          "abc@gmail,com" : {
            "email" : "abc@gmail,com",
            "hasLoggedInWithPassword" : false,
            "name" : "Agenda TEST",
            "timestampJoined" : {
              "timestamp" : 1456950523145
            }
          }
        }
      },
      "shoppingListItems" : {
        "-KBt0MDWbvXFwNvZJXTj" : {
          "-KBt0heZh-YDWIZNV7xs" : {
            "bought" : false,
            "itemName" : "item",
            "owner" : "xyz@gmail,com"
          }
        }
      },
      "uidMappings" : {
        "google:112894577549422030859" : "abc@gmail,com",
        "google:117151367009479509658" : "xyz@gmail,com"
      },
      "userFriends" : {
        "xyz@gmail,com" : {
          "abc@gmail,com" : {
            "email" : "abc@gmail,com",
            "hasLoggedInWithPassword" : false,
            "name" : "Agenda TEST",
            "timestampJoined" : {
              "timestamp" : 1456950523145
            }
          }
        }
      },
    
      "users" : {
        "abc@gmail,com" : {
          "email" : "abc@gmail,com",
          "hasLoggedInWithPassword" : false,
          "name" : "Agenda TEST",
          "timestampJoined" : {
            "timestamp" : 1456950523145
          }
        },
        "xyz@gmail,com" : {
          "email" : "xyz@gmail,com",
          "hasLoggedInWithPassword" : false,
          "name" : "Karol Depka",
          "timestampJoined" : {
            "timestamp" : 1456952940258
          }
        }
      }
    }
    
    然而,在我开始在我的应用程序中实现类似的结构之前,我想澄清一些疑问

    以下是我的相关问题:

  • 在他们的ShoppingList++应用程序中,他们只允许在
    ownerMappings
    节点中分配一个“所有者”。因此,没有其他人可以重命名购物清单。我希望有多个拥有同等权利的“所有者”/“管理员”。这种按用户保留副本的结构是否仍然适用于多个所有者/管理员用户,而不存在数据损坏/去同步或恶作剧的风险
  • 在这样的情况下可能会出现数据损坏:User1脱机,将Widget1重命名为Widget1Prim。当User1脱机时,User2将Widget1共享给User3(User3的副本还不知道重命名)。User1联机并发送有关Widget1重命名的信息(仅发送到他自己和User2的副本,在重命名时客户端代码知道这些副本-不更新User3的副本)。现在,在一个简单的实现中,User3将使用旧名称,而其他名称将使用新名称。这可能很少见,但仍有点令人担忧
  • 第“2”点中的数据损坏情况是否可以/应该通过让某些流程(如AppEngine)监听更改并确保正确传播到所有用户副本来解决
  • 和/或第“2”点中的数据损坏情况是否可以/应该通过实施冗余侦听共享和重命名的更改并将更改传播到每个用户副本来解决,以处理特殊情况?大多数情况下,这是不必要的,因此可能会导致性能/带宽损失和复杂的代码。值得吗
  • 展望未来,一旦我们“在野外”部署了多个版本,考虑到客户机中的代码承担了多少数据处理责任,发展模式难道不会变得很麻烦吗?例如,如果我们添加了一个旧客户端版本还不知道的新关系,它看起来不是很脆弱吗?然后,返回到例如AppEngine(如问题“3”中所述)上的服务器端syncer ensurerer进程
  • 同时拥有每个小部件/购物清单的“主参考副本”似乎是一个好主意,以便为将更新每个用户副本的任何syncer-Ensurer类型的操作提供良好的“真实来源”
  • 关于以这种(冗余)方式构造的数据的rules.json/rules.bolt权限,是否有任何特殊注意事项/陷阱/拦截器
  • PS:我通过
    updateChildren()
    了解原子多路径更新-我肯定会使用它们


    欢迎提供任何其他提示/意见。TIA。

    我建议整个系统只使用一个小部件副本。它将有一个原始用户ID,以及一组可以访问它的用户。小部件树可以保存用户权限和更改历史记录。任何时候进行更改时,都会将分支添加到树中。然后可以将分支“升级”为类似GIT的“主”分支。这将保证数据的完整性,因为以前的版本从未更改或删除。它还将简化您的抓取。。。我想:)


    谢谢但是,如何有效地读取给定(当前登录)用户拥有的所有小部件?你能用示例结构粘贴一些json-s吗?与类似方法有联系吗?顺便说一句,您使用Firebase多久了?您可以保留一个单独的参考ID树,以便直接为该用户访问小部件。谢谢。我已经考虑过这种方法(除了版本控制的想法),但它似乎太慢了(通常只有100个项目需要6秒钟)-《masterKey:abc》是什么?这将是当前正在使用的版本的关键。“我会重视对ShoppingList++示例的一般判断——这是一个值得遵循的示例还是我应该持怀疑态度。“这将是难以置信的广泛和高度主观的,所以我倾向于投票结束。你可能想删除它。一篇文章中的7个问题太多了。它也太宽了。请把范围缩小到一个能在合理的时间/空间内回答的问题。看我的脑袋爆炸了。然而,这篇文章中有一些很好的问题。我要求OP将问题缩小到每篇文章一个,并限制问题的范围、示例代码和Firebase结构。这样做,我们就可以提供帮助。@FrankvanPuffelen-我已经删除了询问ShoppingList++总体可信度的部分。其余的问题应该仍然有效。除了一些人建议的一篇文章中有太多的问题之外-
    { 
      users:[
        bob:{
          widgets:[
            xxx:{
               widgetKey: xyz,
               permissions: *,
               lastEdit... 
            }
          ]
        }
        ...
      ]
      widgets:[
        xyz:{
           masterKey:abc,
           data: {...},
           owner: bob,
        },
        ...
      ]
      widgetHistory:[
        xyz:[
          v1:{
             data:{...},
          },
          v2,
          v3
        ]
        123:[
           ...
        ],
        ...
      ]
     }