在Google App Engine上设计可扩展的产品数据库

时间:2010-09-24 09:35:12

标签: python google-app-engine architecture google-cloud-datastore

我已经构建了一个产品数据库,该数据库分为3部分。每个部分都有一个包含标签的“子”部分。但是我越用它就感觉越不稳定。我每次添加它都需要越来越多的代码才能使它工作。

产品由零件构成,每个零件都是一种类型。每种产品,零件和类型都有一个标签。每种语言都有一个标签。

产品包含2个列表中的部分。一个默认部件列表(每种类型之一)和一个可选部件。

现在我想在混合中添加货币,并决定重新模拟我处理这个问题的整个方式。

我想得到的结果是所有产品对象的列表,其中包含与部件匹配的名称,描述,价格,所有部件和所有类型。对于这些正确的语言标签。

像这样:

product
    - name
    - description (by language)
    - price (by currency)
    - parts
        - part (type name and part name by language)
        - partPrice (by currency)

我当前设置的问题是db.ReferenceProperty和db.ListProperty(db.key)的混合

获取所有数据有点麻烦,需要多个for循环,匹配dict和数据存储区调用。好吧,这有点乱。

重新模型(未经测试)看起来像这样

class Products(db.model)
    name = db.StringProperty()
    imageUrl = db.StringProperty()
    optionalParts = db.ListProperty(db.Key)
    defaultParts = db.ListProperty(db.Key)
    active = db.BooleanProperty(default=True)

    @property
    def itemId(self):
        return self.key().id()

class ProductPartTypes(db.Model):
    name= db.StringProperty()

    @property
    def itemId(self):
        return self.key().id()

class ProductParts(db.Model):    
    name = db.StringProperty()
    type = db.ReferenceProperty(ProductPartTypes)
    imageUrl = db.StringProperty()
    parts = db.ListProperty(db.Key)

    @property
    def itemId(self):
        return self.key().id()


class Labels(db.Model)
    key = db.StringProperty() #want to store a key here
    language = db.StringProperty()
    label = db.StringProperty()

class Price(db.Model)
    key = db.StringProperty() #want to store a key here
    language = db.StringProperty()
    price = db.IntegerProperty()

这里最重要的是我将标签和价格分开了。因此,这些可以包含任何产品,零件或类型的标签和价格。

所以我很好奇,从架构的角度来看,这是一个可靠的解决方案吗?即使每个模型中有数千个条目,这是否会成立?

此外,欢迎任何以良好方式检索数据的提示。我目前的解决方案是首先获取所有数据并将其循环并将其粘贴在dicts中,但感觉它可能会在任何时候失败。

..弗雷德里克

2 个答案:

答案 0 :(得分:3)

您需要记住,App Engine的数据存储区要求您重新考虑通常的数据库设计方法。它首先违背直觉,但如果您希望应用程序可扩展,则必须尽可能地对数据进行非规范化。数据存储区就是这样设计的。

我通常采用的方法是首先考虑在不同的用例中需要进行哪种查询,例如。我需要同时检索哪些数据?按什么顺序?应该索引哪些属性?

如果我理解正确,您的主要目标是获取包含完整详细信息的产品列表。顺便说一句,如果您有其他查询方案 - 即。过滤价格,类型等 - 你也应该考虑它们。

为了从一个查询中获取所需的所有数据,我建议你创建一个看起来像这样的模型:

class ProductPart(db.Model):
    product_name = db.StringProperty()
    product_image_url = db.StringProperty()
    product_active = db.BooleanProperty(default=True)
    product_description = db.StringListProperty(indexed=False) # Contains product description in all languages
    part_name = db.StringProperty()
    part_image_url = db.StringProperty()
    part_type = db.StringListProperty(indexed=False) # Contains part type in all languages
    part_label = db.StringListProperty(indexed=False) # Contains part label in all languages
    part_price = db.ListProperty(float, indexed=False) # Contains part price in all currencies
    part_default = db.BooleanProperty()
    part_optional = db.BooleanProperty()

关于此解决方案:

  • ListProperties设置为 indexed = False以避免 如果你不需要爆炸索引 过滤它们。
  • 为了获得正确的权利 描述,标签或类型,您必须设置 列表值始终按相同的顺序排列。 例如:part_label [0]是 英语,part_label [1]是西班牙语, 等价格和相同的想法 货币。
  • 从此获取实体后 模特,你将不得不做一些 记忆中的操作以便 以合理的方式获取数据 你想要的,也许是在新词典中。

显然,采用这种设计的数据存储区中会有很多冗余 - 但这没关系,因为它允许您以可扩展的方式查询数据存储区。

此外,这并不是您想要的架构的替代品,而是一个专门为您需要做的面向用户的查询而设计的附加模型,即。检索完整的产品/零件信息列表。

这些ProductPart实体可以由后台任务填充,复制位于其他规范化实体中的数据,这些实体将是权威数据源。由于App Engine上有足够的数据存储空间,因此这不应该是一个问题。

答案 1 :(得分:1)

IMO你的设计大多有意义。在阅读完问题陈述后,我确实提出了几乎相同的设计。有几点不同

  • 我将Product和ProductPart的价格作为单独的表格。
  • 其他差异是part_types。如果part_type不多,你可以简单地将它们作为python list / tuple。

part_types = ('wheel', 'break', 'mirror')

它还取决于您预期的查询类型。如果有很多关于自然价格计算的查询(独立于产品和零件信息的其余部分),那么按照您的方式进行设计可能是有意义的。

您已经提到过,您将首先获得所有数据。是不是可以查询?如果你在你的应用程序中获得整个数据,然后在python中进行排序/过滤,那么它会很慢。你在考虑哪个数据库?对我来说,mongodb在这里看起来是个不错的选择。

最后为什么你甚至怀疑1000条记录?您可以事先在db上运行一些测试。

贝斯茨