【发布时间】:2016-03-16 20:54:02
【问题描述】:
实现一个 Android+Web(Angular)+Firebase 应用,具有多对多的关系:用户 Widget(Widget 可以共享给多个用户)。
注意事项:
- 列出用户拥有的所有小部件。
- 用户只能看到共享给他/她的小部件。
- 能够查看共享给定小部件的所有用户。
- 一个小部件可以由多个具有同等权利的用户拥有/管理(修改小部件并更改它的共享对象)。类似于 Google 云端硬盘与特定用户共享的方式。
实现获取(连接样式)的方法之一是通过多个侦听器遵循以下建议:https://www.firebase.com/docs/android/guide/structuring-data.html ("Joining Flattened Data")。
但是我对这种方法有疑问,因为我发现数据加载会慢得令人担忧(至少在 Android 上)——我在另一个问题中问过这个问题——Firebase Android: slow "join" using many listeners, seems to contradict documentation。
所以,这个问题是关于另一种方法的:用户拥有的所有小部件的每个用户副本。与 Firebase+Udacity 教程“ShoppingList++”(https://www.firebase.com/blog/2015-12-07-udacity-course-firebase-essentials.html)中使用的一样。
它们的结构如下所示:
特别是这部分 - userLists:
"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
}
}
}
},
如您所见,购物清单"Test List 1 Rename 2" info 的副本出现在两个地方(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.”中描述)?
- 为每个小部件/购物清单提供一个“主参考副本”,以便为任何会更新- 用户副本?
- 对于以这种(冗余)方式结构化的数据的 rules.json / rules.bolt 权限是否有任何特殊注意事项/陷阱/阻止程序?
PS:我通过updateChildren() 了解原子多路径更新 - 肯定会使用它们。
欢迎任何其他提示/观察。 TIA。
【问题讨论】:
-
“我会重视对 ShoppingList++ 示例的一般判断 - 这是值得效仿的示例还是我应该持怀疑态度。”这将是非常广泛和高度主观的,所以我倾向于投票结束。您可能想要删除它。
-
一篇文章中有 7 个问题太多了。它也方式太宽泛了。请将其缩小到一个可以在合理的时间/空间内回答的问题。
-
我的头爆炸了。但是,帖子中有一些很好的问题。我要求 OP 将问题缩小到每个帖子一个,并限制问题、示例代码和 Firebase 结构的范围。这样做,我们可以提供帮助。
-
@FrankvanPuffelen - 我已经删除了一般询问 ShoppingList++ 可信度的部分。其余的问题应该仍然成立。除了一些人建议的帖子中有太多问题之外 - 我将尝试拆分。
标签: firebase database-schema angularfire firebase-realtime-database