用户表的最佳数据库设计(模型)

时间:2010-01-17 11:24:52

标签: database google-app-engine database-design model

我正在使用google appengine和django开发一个Web应用程序,但我认为我的问题更为笼统。

用户可以创建表,看看:表在数据库中没有表示为TABLES。我举个例子:

First form:
 Name of the the table: __________
 First column name: __________
 Second column name: _________
 ...

列数不固定,但最大值(例如100)。每列中的类型都是相同的。

Second form (after choosing a particular table the user can fill the table):
 column_name1: _____________
 column_name2: _____________
 ....

我正在使用这个解决方案,但这是错误的:


class Table(db.Model):
    name = db.StringProperty(required = True)

class Column(db.Model):
    name = db.StringProperty(required = True)
    number = db.IntegerProperty()
    table = db.ReferenceProperty(table, collection_name="columns")

class Value(db.Model):
    time = db.TimeProperty()
    column = db.ReferenceProperty(Column, collection_name="values")

当我想列出一个表时,我会选择它的列,并从每一列中取出它们的值:


    data = []
    for column in data.columns:
        column_data = []
        for value in column.values:
            column_data.append(value.time)
        data.append(column_data)
    data = zip(*data)

我认为问题是值的顺序,因为一列的顺序与其他列的顺序不同是不正确的。我正在等待这个错误(但直到现在我从未见过它):

Table as I want:   as I will got:
a z c                 a e c
d e f                 d h f
g h i                 g z i

更好的解决方案?也许使用ListProperty

5 个答案:

答案 0 :(得分:2)

这是一个可能为您提供帮助的数据模型:

class Table(db.Model):
 name = db.StringProperty(required=True)
 owner = db.UserProperty()
 column_names = db.StringListProperty()

class Row(db.Model):
 values = db.ListProperty(yourtype)
 table = db.ReferenceProperty(Table, collection_name='rows')

我的推理: 您实际上不需要单独的实体来存储列名称。由于所有列都具有相同的数据类型,因此您只需要存储名称,并且它们存储在列表中的事实会为您提供隐含的订单号。

通过将值存储在Row实体的列表中,您可以使用 column_names 属性中的索引来查找 values 属性中的匹配值。

通过将一行的所有值存储在一个实体中,不会有值出现在正确顺序之外。

警告说: 如果表在填充数据后可以添加列,则此模型将无法正常工作。为了实现这一点,每次添加一列时,属于该表的每个现有行都必须在其列表中附加一个值。如果可以在数据存储区中有效地存储字典,这不会有问题,但列表实际上只能附加到。

或者,您可以使用Expando ...

另一种可能性是您可以将 Row 模型定义为Expando,它允许您在实体上动态创建属性。您可以仅为包含值的列设置列值,并且还可以在表中包含数据后向表中添加列,而不会破坏任何内容:

class Row(db.Expando):
    table = db.ReferenceProperty(Table, collection_name='rows')

    @staticmethod
    def __name_for_column_index(index):
        return "column_%d" % index

    def __getitem__(self, key):
        # Allows one to get at the columns of Row entities with
        # subscript syntax:
        # first_row = Row.get()
        # col1 = first_row[1]
        # col12 = first_row[12]
        value = None
        try:
            value = self.__dict__[Row.__name_for_column_index]
        catch KeyError:
            # The given column is not defined for this Row
            pass
        return value

    def __setitem__(self, key, value):
        # Allows one to set the columns of Row entities with
        # subscript syntax:
        # first_row = Row.get()
        # first_row[5] = "New values for column 5"

        self.__dict__[Row.__name_for_column_index] = value
        # In order to allow efficient multiple column changes,
        # the put() can go somewhere else.
        self.put()

答案 1 :(得分:1)

为什么不为行号添加一个IntegerProperty值,每次添加一行新值时都会增加它,然后你可以通过rowNumber排序来重建表。

答案 2 :(得分:0)

除非用户的'表'实际存储在关系数据库中作为真实表,否则您将为自己的生活变得非常困难。找到一些实际创建表格的方法,并使用RDBMS的强大功能,或者重新创建一个非常复杂和复杂的轮子。

答案 3 :(得分:0)

这是我将使用的概念性想法: 我会为数据存储创建两个类:

  1. table这可以作为一个 字典,存储结构 你的应用程序会伪表 创建。它会有两个字段: table_name,column_name, column_order。其中column_order 会给出这个位置 表格中的列

  2. data 这将存储实际数据 伪表。它会有 四个字段:row_id,table_name, column_name,column_data。 ROW_ID 数据也是一样的 属于同一行而且会 对于跨越数据的数据是唯一的 各种伪表。

答案 4 :(得分:0)

将数据放入LongBlob。

数据库的强大之处在于能够搜索和组织数据,这样您才能获得性能和简单问题所需的部分:您不需要整个数据库,只需要一部分它想快点。但据我所知,当您检索用户的数据时,您将检索所有数据并显示它。因此,您不需要以正常的“数据库”方式来处理数据。

我建议简单地将单个用户的整个数据格式化并存储在具有合适类型的单个列中(例如,LongBlob)。格式将是一个具有列和行类型的列表的对象。然后用您用来与数据库通信的任何语言定义对象。

(真实)数据库中的列将是:User int,TableNo int,Table Longblob。 如果user8有3个表,则您将拥有以下行:

8, 1, objectcontaintingtable1;
8, 2, objectcontaintingtable2;
8, 3, objectcontaintingtable3;
相关问题