建模分层数据 - GAE

Ivá*_*lta 5 python google-app-engine bigtable

我是google-app-engine和google datastore(bigtable)的新手,我有些疑惑,这可能是设计所需数据模型的最佳方法.

我需要创建一个层次结构模型,类似于产品目录,每个域都有一些深层子域.目前,产品的结构变化小于读取要求.葡萄酒示例:

  • 起源(Toscana,Priorat,Alsacian)
  • 酒庄(仅属于一个起源)
  • 葡萄酒(仅属于一个酒庄)

所有关系都是不相交和不完整的.此外,按照要求的顺序,我们可能需要存储每种葡萄酒的使用计数器(可能需要交易)

根据文档的顺序,似乎有不同的潜在解决方案:

  • 祖先管理.使用父关系和交易
  • 伪祖先管理.使用db.ListProperty(db.Key)模拟祖先
  • 的ReferenceProperty.明确指定类之间的关系

但是为了获得葡萄酒的预期要求......有时候是按品种,有时是原产地,有时是酒庄...我担心使用这些结构的查询的行为(比如关系模型中的多个连接).如果你要求一个家庭的产品...你需要加入产品树的最后深度限定符,并加入自家庭以来)

也许最好创建一些重复的信息(按照谷歌团队的建议顺序:操作很昂贵,但存储不是,所以不应该看到重复的内容是主要问题)

其他类似问题的一些回答表明:

  • 将所有父ID作为层次结构存储在字符串中...就像路径属性一样
  • 复制Drink实体与树中所有父母之间的关系......

有什么建议?


嗨,威尔,

我们的情况更像是一种严格的分层方法,如第二个例子所示.并且查询用于检索产品列表,只检索一个不常见的.

我们需要从Origin,Winery或Variety中检索所有葡萄酒(如果我们认为该品种是严格分层树的另一个节点,仅仅是一个例子)

一种方法可能是包含路径属性,如您所述:

  • /产地/ {ID} /酒厂/ {ID} /各种/ {ID}

允许我从应用如下查询的各种葡萄酒中检索葡萄酒列表:

wines_query = Wine.all()
wines_query.filter('key_name >','/origin/toscana/winery/latoscana/variety/merlot/')
wines_query.filter('key_name <','/origin/toscana/winery/latoscana/variety/merlot/zzzzzzzz')
Run Code Online (Sandbox Code Playgroud)

或者来自Origin:

wines_query = Wine.all()
wines_query.filter('key_name >','/origin/toscana/')
wines_query.filter('key_name <','/origin/toscana/zzzzzz')
Run Code Online (Sandbox Code Playgroud)

谢谢!

Wil*_*hen 1

我不确定除了问题中提到的查询之外,您还需要执行哪些类型的查询,但是将数据存储在显式的祖先层次结构中将使您询问的查询很容易消失。

例如,要获取来自特定产地的所有葡萄酒:

origin_key = db.Key.from_path('Origin', 123)
wines_query = db.Query(Wine).ancestor(origin_key)
Run Code Online (Sandbox Code Playgroud)

或者从特定酒庄获取所有葡萄酒:

origin_key = db.Key.from_path('Origin', 123)
winery_key = db.Key.from_path('Winery', 456, parent=origin_key)
wines_query = db.Query(Wine).ancestor(winery_key)
Run Code Online (Sandbox Code Playgroud)

并且,假设您将品种存储为 Wine 模型上的属性,则特定品种的所有葡萄酒都像这样简单

wines_query = Wine.all().filter('variety =', 'merlot')
Run Code Online (Sandbox Code Playgroud)

这种严格的分层方法的一个可能的缺点是它可以强加给您一种 URL 方案。具有看起来像的层次结构

Origin -> Winery -> Wine
Run Code Online (Sandbox Code Playgroud)

您必须知道葡萄酒产地酒厂的密钥名称或 ID,才能构建检索该葡萄酒的密钥。除非您已经获得了葡萄酒密钥的字符串表示形式。这基本上迫使您采用以下形式之一的葡萄酒 URL:

  • /origin/{id}/winery/{id}/wine/{id}
  • /wine/{opaque and unfriendly datastore key as a string}

(第一个 URL 当然可以替换为查询字符串参数;重要的是您需要三个不同的信息来识别给定的葡萄酒。)

不过,也许我还没有想到这些 URL 方案还有其他替代方案。