在Cloud Firestore中管理非规范化/重复数据

时间:2019-01-18 13:03:03

标签: firebase google-cloud-firestore

如果您决定在Firestore中对数据进行非规范化/复制以优化读取,那么通常使用什么模式(如果有)来跟踪重复的数据,以便可以正确地对其进行更新以避免数据不一致?

例如,如果我拥有Pinterest板之类的功能,平台上的任何user都可以将我的post固定到自己的board上,那么您将如何跟踪许多位置中的重复数据?

关于为数据可以存在的每个唯一位置创建一个类似关系的表,该表用于重建需要更新的路径。

例如,创建一个users_posts_boards集合,该集合首先是一个userIDs子集合的postIDs集合,最后又具有一个boardIDs的子集合boardOwnerID。然后,您可以使用它们来重构post(例如/users/[boardOwnerID]/boards/[boardID]/posts/[postID])的重复数据的路径吗?

如果另外可以将postsgroupslists共享,您是否会继续创建users_posts_groupsusers_posts_lists集合和子集合来跟踪重复项数据以同样的方式?

或者,您是否有一个posts_denormalization_tracker只是唯一的postIDs的集合,其中包括post被复制到的位置的子集合?

{
  postID: 'someID',
  locations: ( <---- collection
    "path/to/post/location1",
    "path/to/post/location2",
    ...
  )
}

这意味着您基本上需要通过Cloud Functions完成所有对Firestore的写入操作,出于安全原因,这些功能可以跟踪此数据。...除非Firestore安全规则足够强大,以允许对{ {1}}子集合,不允许对该子集合或父/posts_denormalization_tracker/[postID]/locations集合进行读取或更新。

我基本上是在寻找一种跟踪严重的非规范化数据的理智方法。

编辑:是的,另一个很好的例子是将postIDs作者的post信息嵌入到每个profile中。想象一下,在整个平台上共享时,地狱试图保持所有最新状态,然后post更新其user

1 个答案:

答案 0 :(得分:0)

由于您来自here的请求,我在问这个问题。

复制数据时,请记住一件事。用与添加数据相同的方式,您需要对其进行维护。换句话说,如果要更新/删除对象,则需要在对象存在的每个位置进行处理。

  

通常使用什么模式(如果有的话)来跟踪重复的数据,以便可以正确地更新它们以避免数据不一致?

要跟踪拥有一致数据所需执行的所有操作,我们将所有操作添加到批处理中。您可以在不同的引用上添加一个或多个 update 操作,以及 delete add 操作。为此,请参见:

  

关于为数据可以存在的每个唯一位置创建一个类似关系的表,该表用于重建需要更新的路径。

我认为不需要添加额外的“类似关系的表”,但是如果您对此感到不舒服,请继续使用它。

  

然后,您可以使用它们来重构帖子的重复数据的路径(例如/users/[boardOwnerID]/boards/[boardID]/posts/[postID])吗?

是的,您需要将每个文档的ID传递给每个document()方法,以使更新操作起作用。不幸的是,Cloud Firestore的文档路径中没有通配符。您必须通过文档ID来识别它们。

  

或者,您是否会拥有一个posts_denormalization_tracker,它只是唯一的postID的集合,其中包括该帖子被复制到的位置的子集合?

我认为这也是不必要的,因为它需要额外的读取操作。由于Firestore中的所有内容都是关于读写次数的,所以我认为您应该再次考虑这种方法。请参阅Firestore usage and limits

  

除非Firestore安全规则足够强大,以允许对/ posts_denormalization_tracker / [postID] / locations子集合进行添加操作,但不允许读取或更新子集合或父postIDs集合。

Firestore security rules如此强大。您还可以允许阅读或编写甚至应用有关所需的每个CRUD操作的安全规则。

  

我基本上是在寻找一种跟踪严重的非规范化数据的理智方法。

我能想到的最简单的方法是将操作添加到键和值类型的数据结构中。假设我们有一张看起来像这样的地图:

Map<Object, DocumentRefence> map = new HashMap<>();
map.put(customObject1, reference1);
map.put(customObject2, reference2);
map.put(customObject3, reference3);
//And so on

遍历整个地图,并将所有这些键和值添加到批处理中,然后提交批处理。