2010-01-17 48 views
3

我正在開發一個使用谷歌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

+3

這個問題不是很清楚;您需要的表格的性質與您獲得的表格的性質與您顯示的數據存儲模型有點模糊不清。另外,我不確定您是否有問題,或者只是擔心您會遇到問題。 – 2010-01-17 12:44:36

+0

問題很簡單:用戶可以創建一個表。一個表格是用戶看作是一個表格的東西,但並不是必要的,它被作爲一個表格存儲在數據庫中。用戶選擇表中有多少列和他們的名字。用戶用數據填充表格。表中的每個條目都是相同的類型。用戶可以創建多個表。 看到這個:http://donotmissthebus.appspot。com/path /(現在表中的列固定爲兩個:開始和結束,bus *未實現)。 我認爲我的解決方案不是非常線性和容易出錯的。 – 2010-01-17 21:58:24

+0

這種阻抗不匹配可能是關係數據庫是工作的錯誤工具的證據。你是否考慮過一個鍵值存儲,例如:「無數據庫」數據庫,還是具有API的分佈式文件系統之一? – 2010-01-27 15:16:08

回答

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') 

我的理由: 你並不真的需要一個單獨的實體來存儲列名稱。由於所有列都具有相同的數據類型,因此只需存儲名稱,並且它們存儲在列表中的事實爲您提供了隱含的訂單號。

通過在行實體列表存儲的值,您可以使用一個索引COLUMN_NAMES屬性查找在屬性的匹配值。

通過將一行中的所有值一起存儲在單個實體中,不存在出現超出其正確順序的值的可能性。

提醒注意: 如果表填充數據後可以添加列,則該模型將無法正常工作。爲了做到這一點,每次添加列時,屬於該表的每個現有行都必須具有附加到其列表的值。如果有可能在數據存儲中有效地存儲字典,這不會是一個問題,但是列表實際上只能被附加到。

或者,你可以使用Expando的...

另一種可能性是,你可以定義模型在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() 
+0

正如我以前所說的這種解決方案是好的,但問題是如何處理空值,例如連續的例子不是每一列都被填充。 – 2010-01-27 18:13:01

+0

當您添加一個新行時,用無替換未填充的列。 – 2010-01-27 19:24:35

1

爲什麼不給rowNumber添加一個IntegerProperty作爲Value值,並在每次添加一行新值時增加它,然後通過按rowNumber排序來重構表。

+0

我想過了,它解決了我的問題,但我正在尋找一個完全不同的解決方案。我認爲我的問題不是一個新問題,很多人已經以更好的方式解決了這個問題。 – 2010-01-20 22:25:00

+0

我認爲你描述它的方式是大多數人使用關係數據庫的方式,但由於App Engine的數據庫是無模式的,你可以給Table一個列名列表作爲ListProperty,然後有一個Row類,一個時間表。 – mckeed 2010-01-20 22:56:02

+0

是的,但這種情況下的問題是處理空值。 – 2010-01-21 09:11:49

0

你打算讓生活非常困難的,除非自己的用戶「表」實際上是在關係數據庫真實的表存儲。找到一些實際創建表格的方式,並使用RDBMS的力量,或者您正在重塑一個非常複雜和複雜的車輪。

+0

我必須爲用戶授予CREATE權限嗎?我認爲這很糟糕。不過,我正在使用谷歌應用程序引擎,所以我正在使用模型,而不是直接與數據庫。請記住,每個用戶都可以創建數百個「表」 – 2010-01-21 22:17:33

+0

不,不一定。讓用戶將他們表的規格提交給爲其創建表的存儲過程。該存儲過程可以有很多邏輯來處理允許的表格類型(以及多少個表格),而且您不需要爲終端用戶提供比您更大的自由度。 – 2010-01-21 22:36:25

0

這是概念性想法,我使用: 我將用於數據存儲創建兩個類:

  1. table這將作爲一個 詞典,存儲 的僞表的結構你的應用程序將創建 。它會有兩個字段: table_name,column_name, column_order。其中column_order 將使 列的位置在表中

  2. data 這將存儲實際數據中 僞表。它會有 四個字段:row_id,table_name, column_name,column_data。 row_id 對於屬於同一行的數據 應該是相同的,並且 對於跨各個僞表的數據是唯一的。

+0

與我的解決方案沒有多大區別。正如mckeed所說,我只需要一個row_id。 – 2010-01-25 22:01:07

0

將數據放入LongBlob中。

數據庫的強大功能是能夠搜索和組織數據,以便您只能獲得性能和簡單性問題所需的部分:不需要整個數據庫,只需要一個數據庫它的一部分,並希望它快。但根據我的理解,當您檢索用戶的數據時,您將檢索並顯示它。所以你不需要以正常的「數據庫」方式來刻錄數據。

我建議的是簡單地將單個用戶的整個數據格式化並存儲在具有合適類型(例如LongBlob)的單個列中。格式將是一個具有列和行類型列表的對象。你可以用你用來與數據庫通信的任何語言來定義對象。

您的(真實)數據庫中的列應該是:User int,TableNo int,Table Longblob。 如果user8有3個表,你將有以下行:

8, 1, objectcontaintingtable1; 
8, 2, objectcontaintingtable2; 
8, 3, objectcontaintingtable3;