【问题标题】:What are some good examples for App Engine NDB commenting models?App Engine NDB 评论模型有哪些好的示例?
【发布时间】:2014-05-15 18:42:35
【问题描述】:

我正在尝试在 App Engine 中为我的博客建模一个基本的线性评论系统(您可以在 http://codeinsider.us 看到它)。我的主要对象类别是:

用户, 文章, 评论

一个用户将拥有许多 cmets,并且应该能够一目了然地查看他们的 cmets。

一篇文章会有很多cmets,应该一目了然。

一条评论将与一位用户和一篇文章相关联。

我知道如何在标准的关系数据库中构建它 - 例如,我可能有用于 cmets、用户和文章的单独表,使用外键将它们绑定在一起,文章和用户的唯一性约束,而没有cmets 等。没什么特别的。

在 Python App Engine 中使用 NDB 进行建模的最佳方法是什么? ndb.KeyProperty 看起来很有趣,StructuredProperty 也是如此。我不认为我可以使用 StructuredProperty,因为评论可以“属于”用户和文章。但是对于 ndb.KeyProperty,keyProperty 似乎不做任何检查或验证逻辑,所以我必须自己实现。

我能做的另一件事就是认输,将巨大的 JSON blob 存储在代表 cmets 的键和种类的用户和文章中。这可能不是一个糟糕的解决方案。

有什么想法吗?

编辑: 这将是高读低写。我可能会在 cmets 上增加一些参与度(upvotes/downvotes),但即便如此,它也会非常重视阅读。

【问题讨论】:

    标签: python google-app-engine nosql


    【解决方案1】:

    我建议您仔细考虑您计划提供哪些功能,因为以某种方式构建模型可能会在将来难以进行某些更改。

    我会这样做:

    首先,假设一些最终的一致性。无论您如何设计它,您都会在某些查询中获得一些最终的一致性。

    在文章中创建一个 KeyProperty“所有者”来存储 user_key。如果您想在查询单个用户的文章时实现强一致性,那么不要使用“所有者”KeyProperty,只需将 user_key 设为文章的父级(这将为用户及其文章创建一个实体组,在这里很好)。

    使用 cmets 你可以做更多的事情。

    1. 如果您预计少于 100 个(取决于文章大小 datastore 可以更多) cmets 为每篇文章创建一个 cmets Article 中的 KeyProperty(repeated=True) 用于存储所有 cmets 密钥 然后用 get_multi 获取它们(强一致性)。

      创建评论并修改文章 cmets 属性 你可能需要一个事务,因为你会想要完成 两个操作或非他们。但是..这两个实体不在 相同的实体组,因此:1)使用跨组事务或 2)进行 文章评论的父级(第二个选项将有一些 后果稍后讨论)cmets 的计数很容易,但 如前所述,限制为 100 个或更多 cmets。

    2. 创建一个带有两个 KeyProperties 的 Comment ndb 模型,“所有者”和 “文章”。本文将通过查询获取 cmets。查询 您最终将拥有的文章中的所有 cmets 一致性,除非您将文章设为评论的父级 (在这种情况下,当然不要创建文章 KeyProperty)。这 方法允许很多 cmets。

    使用实体组的问题是,例如,如果您允许对 cme​​ts 进行投票,那么对每个评论的单个写入操作将阻止受影响文章的洞实体组中的任何写入。因此其他用户的创建和投票可能会受到影响。但是,如果您希望获得很少的选票并且保持实体组较小,则不要真正关心这一点。

    如果您想允许评论投票,这可能会变得非常复杂,因为您可能希望每个用户只投一票。这将需要之前需要考虑的额外关系。

    就我个人而言,我更喜欢几乎总是假设最终的一致性。

    更多方法是可能的,但我喜欢这两种。

    【讨论】:

      【解决方案2】:

      高读低写场景是 GAE 的专长,所以这对你来说是件好事。

      我会利用 GAE 模型的 ancestry feature,因为它可以确保您在实体组内进行事务/原子操作。我想你不需要太多,但它仍然是一件好事。

      正确的结构取决于您处理/使用数据的方式。我假设您博客中的典型案例是为一篇文章显示 cmets,因此,我会让您的评论模型成为您文章模型的子模型 - 然后您可以查询 cmets 以获得某个(文章)祖先,这将规模宏大。

      我会在评论中为作者添加一个 KeyProperty,因为它主要用于从我假设的密钥中获取用户。如果您想扩展 KeyProperty 功能,您可以这样做。这是一个关于如何在 db 中使用 KeyProperty behave as ReferenceProperty 的示例。 (第 1 点。)

      【讨论】:

      • 谢谢!因此,使用祖先功能对文章 -> 评论是有意义的,但是每次用户想要查看他们所有的 cmets 时,我是否仍然需要执行 N 个额外的读取查询?
      • 另外,如果我理解正确的话,一篇文章的 cmets 是否需要“N”次阅读?我目前正在尝试的解决方案是一种非规范化——每篇文章都有一个 cmets 的 StructuredProperty 列表,而用户有相同的 cmets 的 StructuredProperty 列表(实际评论,没有参考)。我正在使用跨组事务以正确的方式进行更新。这里的权衡似乎是过多的并发写入会导致一些轰炸,但我暂时还可以......
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-27
      • 1970-01-01
      相关资源
      最近更新 更多