【问题标题】:Datastore model design with ancestors具有祖先的数据存储模型设计
【发布时间】:2018-01-29 10:26:46
【问题描述】:

我现在已经将 Datastore 用于两个项目,但是对于这两个项目,我都未能利用祖先关系。经过大量的阅读和研究,我相信我终于明白了如何设计一个出色的 Datastore 模型。

想象一个类似于 Reddit/Instagram 的网站,用户可以在其中创建其他用户可以订阅的自己的类别(类似于 Subreddits)。用户可以互相关注,不同用户上传的图片会上传到这些分类中,并显示在特定用户的个人资料下(如在 Instagram 中)。考虑到这一点,我认为这是理想的设计:

Category
- User
- - Image
- Subscriber
User
- Follower
- Following

使用此 Datastore 模型,我相信应该可以轻松检索“用户 id”或“类别 id”上传的所有图像、订阅“类别 id”的所有用户、上传到“类别 id”的所有图像。所有关注或被“用户id”关注的用户,用户上传的所有图片都被“用户id”关注。

我非常感谢一些 Datastore 专家的反馈和改进它的潜在方法(我特别好奇在两个不同位置使用“用户”作为祖先是否有任何问题,因为它是“类别”的子级' 在一个地方,但不在另一个地方)..


我希望这将有助于使问题更易于理解/回答:)

我有以下实体:

Category
- ID int64
- Name string
- etc..

User
- Username string (NameKey)
- Password []byte
- etc..

Image
- ID int64
- StorageID string
- MD5Hash string
- etc..

Follow
- ID int64
- Follower string
- Following string

Category、User、Image 和 Follow 是实体,ID、Name、Username 等是属性名称。

因此 Image 实体将来自 User(上传图片的人)和 Category 祖先

Follow 实体将继承自 User 祖先

至于订阅者,我不确定是否最好创建一个类似于 Follow 的全新实体(在这种情况下,它可能包括用户首次订阅的日期),还是让它成为一个属性

【问题讨论】:

  • 这到底是什么语言?
  • @Y2H 我用的是Golang,但我相信无论使用什么语言设计一个合适的Datastore model with ancestors都是一样的(我的意思是祖先关系应该是一样的)
  • 是的,应该是。不幸的是,由于我不熟悉 Go,我无法理解您的模型,因此无法为您提供帮助。很抱歉没有提供帮助。
  • 我认为更重要的是理解/回答问题的难易程度。这是一个非常开放的结尾,这使得以问答形式回复变得更加困难。例如,不清楚哪些是实体,哪些是属性。
  • @DanMcGrath 你是对的,在我更新它以指定实体后,我可以看到问题有点完全不同的观点:)

标签: database google-cloud-datastore google-cloud-platform data-modeling


【解决方案1】:

实体组(具有相同根祖先的所有实体,包括根祖先)在查询时更多地是关于一致性单元。这种设计的一个问题是可扩展性,因为实体组被限制为每秒持续 1 个事务(您可以爆发更高)。

使用当前的设计,您在一个类别中的所有查询都将保持高度一致,但您将被限制为每秒 1 个新图像。

由于对一个类别中的所有图像具有高度一致的视图可能不如确保您可以处理增长那么重要,因此最好让图像从根用户实体下降(因此用户正在寻找他们的自己的图像是强一致的)并且类别只是图像实体属性中的一个 id。

Category
- ID int64
- Name string
- OwnerUserID string
- etc..

User
- Username string (NameKey)
- Password []byte
- etc..

Image (descends from User)
- ID int64
- StorageID string
- MD5Hash string
- CategoryID int64
- etc..

现在列出用户 123 的所有图像(高度一致):

SELECT * FROM Image WHERE __key__ HAS ANCESTOR (User, 123)

列出类别 456 中用户 123 的所有图像(高度一致):

SELECT * FROM Image WHERE __key__ HAS ANCESTOR (User, 123) AND CategoryID = 456

列出类别 456 中的所有图像(最终一致):

SELECT * FROM Image WHERE CategoryID = 456

列出所有图片(最终一致)

SELECT * FROM Image

【讨论】:

  • 哇,这太棒了。如果我理解正确,Category 不应该是 Image 的祖先的原因不是因为它是“嵌套”的祖先关系(嵌套的祖先完全没问题,对吧?),而是因为不同的用户可能会将图像上传到 Category(对于每秒 1 次写入将是一个问题.. 类似于不同的 Reddit 用户将提交提交到给定的 subreddit 的方式),但对于给定的用户,如果每秒只能上传 1 张图像不是问题(我也相信在这个如果应该可以使用multiput一起上传一批图像)
  • 类似地,Follow 实体可以将 User 作为根祖先,因为给定的 User 每秒关注的次数不会超过一个(如 Twitter/Instagram),除非他们将其自动化(在这种情况下,它也应该如果写 Follow 操作有延迟也没关系)
  • 你明白了,两个 cmets(Inc multiput)都是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多