代码之家  ›  专栏  ›  技术社区  ›  Iván Peralta

分层数据建模-GAE

  •  5
  • Iván Peralta  · 技术社区  · 14 年前

    我是google app engine和google datastore(bigtable)的新手,我有一些疑问,按顺序,这可能是设计所需数据模型的最佳方法。

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

    • 起源(托斯卡纳、普里萨特、阿尔萨斯)
    • 酿酒厂(仅属于一个产地)
    • 葡萄酒(仅属于一家酿酒厂)

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

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

    • 祖先管理。使用父关系和事务
    • 伪祖先管理。使用db.listproperty(db.key)模拟祖先
    • 引用属性。明确指定类之间的关系

    但是按照预期的要求去买葡萄酒…有时根据品种,有时根据产地,有时通过酿酒厂…我担心使用这些结构的查询行为(比如关系模型中的多个连接)。如果你要一个家庭的产品…您需要加入产品树中的最后一个深度限定符,并加入自系列以来的限定符)

    也许最好创建一些重复的信息(按照谷歌团队的建议顺序:操作成本很高,但存储空间不高,所以不应该将重复的内容视为主要问题)

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

    • 将所有父ID作为层次结构存储在字符串中…像路径属性
    • 复制饮料实体和树上所有父母之间的关系…

    有什么建议吗?


    嗨,威尔,

    我们的案例更像您在第二个示例中所表示的那样是一种严格的层次结构方法。而查询是为了检索产品列表,只检索一个是不常见的。

    我们需要从一个产地、一个酿酒厂或一个品种中检索所有的葡萄酒(如果我们认为品种是严格等级树的另一个节点,仅举一个例子)

    一种方法可以包括路径属性,如您所提到的:

    • /产地/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')
    

    或者像这样起源于:

    wines_query = Wine.all()
    wines_query.filter('key_name >','/origin/toscana/')
    wines_query.filter('key_name <','/origin/toscana/zzzzzz')
    

    谢谢您!

    1 回复  |  直到 14 年前
        1
  •  1
  •   Will McCutchen    14 年前

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

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

    origin_key = db.Key.from_path('Origin', 123)
    wines_query = db.Query(Wine).ancestor(origin_key)
    

    或者从一个特定的酿酒厂获得所有的葡萄酒:

    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)
    

    而且,假设您将品种存储在葡萄酒模型的属性中,那么特定品种的所有葡萄酒都非常简单

    wines_query = Wine.all().filter('variety =', 'merlot')
    

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

    Origin -> Winery -> Wine
    

    你必须知道葡萄酒的主要名称或产地 酿酒厂为了建造一把钥匙来取回那瓶酒。除非你已经有了酒钥匙的字符串表示。这基本上迫使您使用以下形式之一的葡萄酒URL:

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

    (第一个URL当然可以用querystring参数替换;重要的是,您需要三个不同的信息来标识给定的葡萄酒。)

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