我有一個星型模式架構的數據庫,我想在SQLAlchemy中表示。現在我遇到了如何以最好的方式完成這個問題。現在我有很多自定義連接條件的屬性,因爲數據存儲在不同的表中。 這將是很好,如果有可能重新使用不同的事實tablesw維度,但我還沒有想出如何可以做得很好。SQLAlchemy中的星型模式
7
A
回答
19
星型模式中的典型事實表包含所有維表的外鍵引用,因此通常不需要自定義連接條件 - 它們是從外鍵引用自動確定的。
例如有兩個事實表星型模式會是什麼樣子:
Base = declarative_meta()
class Store(Base):
__tablename__ = 'store'
id = Column('id', Integer, primary_key=True)
name = Column('name', String(50), nullable=False)
class Product(Base):
__tablename__ = 'product'
id = Column('id', Integer, primary_key=True)
name = Column('name', String(50), nullable=False)
class FactOne(Base):
__tablename__ = 'sales_fact_one'
store_id = Column('store_id', Integer, ForeignKey('store.id'), primary_key=True)
product_id = Column('product_id', Integer, ForeignKey('product.id'), primary_key=True)
units_sold = Column('units_sold', Integer, nullable=False)
store = relation(Store)
product = relation(Product)
class FactTwo(Base):
__tablename__ = 'sales_fact_two'
store_id = Column('store_id', Integer, ForeignKey('store.id'), primary_key=True)
product_id = Column('product_id', Integer, ForeignKey('product.id'), primary_key=True)
units_sold = Column('units_sold', Integer, nullable=False)
store = relation(Store)
product = relation(Product)
但是,假設你想減少在任何情況下樣板。我想創建本地發電機,其在事實表配置自己的維類:
其中class Store(Base):
__tablename__ = 'store'
id = Column('id', Integer, primary_key=True)
name = Column('name', String(50), nullable=False)
@classmethod
def add_dimension(cls, target):
target.store_id = Column('store_id', Integer, ForeignKey('store.id'), primary_key=True)
target.store = relation(cls)
情況下使用會是這樣:
class FactOne(Base):
...
Store.add_dimension(FactOne)
但是,有一個問題這一點。假設您要添加的維列是主鍵列,則映射器配置將失敗,因爲在映射設置之前,類需要設置其主鍵。因此,假設我們使用的聲明(你會看到下面有一個很好的效果),使這種方法的工作,我們不得不使用instrument_declarative()
功能,而不是標準的元類:
meta = MetaData()
registry = {}
def register_cls(*cls):
for c in cls:
instrument_declarative(c, registry, meta)
然後我們倒是做線沿線的東西:
class Store(object):
# ...
class FactOne(object):
__tablename__ = 'sales_fact_one'
Store.add_dimension(FactOne)
register_cls(Store, FactOne)
如果你確實有一個很好的理由,自定義連接條件,只要有一些模式是如何創造這些條件,您可以生成與add_dimension()
:
class Store(object):
...
@classmethod
def add_dimension(cls, target):
target.store_id = Column('store_id', Integer, ForeignKey('store.id'), primary_key=True)
target.store = relation(cls, primaryjoin=target.store_id==cls.id)
但是,如果你使用2.6,最後一件很酷的事情就是把add_dimension
變成一個類裝飾器。這裏有一個清理一切的例子:
from sqlalchemy import *
from sqlalchemy.ext.declarative import instrument_declarative
from sqlalchemy.orm import *
class BaseMeta(type):
classes = set()
def __init__(cls, classname, bases, dict_):
klass = type.__init__(cls, classname, bases, dict_)
if 'metadata' not in dict_:
BaseMeta.classes.add(cls)
return klass
class Base(object):
__metaclass__ = BaseMeta
metadata = MetaData()
def __init__(self, **kw):
for k in kw:
setattr(self, k, kw[k])
@classmethod
def configure(cls, *klasses):
registry = {}
for c in BaseMeta.classes:
instrument_declarative(c, registry, cls.metadata)
class Store(Base):
__tablename__ = 'store'
id = Column('id', Integer, primary_key=True)
name = Column('name', String(50), nullable=False)
@classmethod
def dimension(cls, target):
target.store_id = Column('store_id', Integer, ForeignKey('store.id'), primary_key=True)
target.store = relation(cls)
return target
class Product(Base):
__tablename__ = 'product'
id = Column('id', Integer, primary_key=True)
name = Column('name', String(50), nullable=False)
@classmethod
def dimension(cls, target):
target.product_id = Column('product_id', Integer, ForeignKey('product.id'), primary_key=True)
target.product = relation(cls)
return target
@Store.dimension
@Product.dimension
class FactOne(Base):
__tablename__ = 'sales_fact_one'
units_sold = Column('units_sold', Integer, nullable=False)
@Store.dimension
@Product.dimension
class FactTwo(Base):
__tablename__ = 'sales_fact_two'
units_sold = Column('units_sold', Integer, nullable=False)
Base.configure()
if __name__ == '__main__':
engine = create_engine('sqlite://', echo=True)
Base.metadata.create_all(engine)
sess = sessionmaker(engine)()
sess.add(FactOne(store=Store(name='s1'), product=Product(name='p1'), units_sold=27))
sess.commit()
相關問題
- 1. 星型模式vs雪花模式
- 2. 插入星型模式
- 3. 性能星型模式(BI)
- 4. 星型模式設計
- 5. 星型模式,代理鍵
- 6. SQLAlchemy - 將表達式附加到模型
- 7. 轉換一個無星型模式數據庫星型模式數據庫
- 8. 星型模式建模 - 多到許多
- 9. SQLAlchemy的LOAD_ONLY對父模型
- 10. sqlAlchemy模型的問題
- 11. 所有模型的SQLAlchemy「event.listen」
- 12. 星型模式的缺點是什麼?
- 13. 來自3NF的星型模式設計
- 14. sqlalchemy模型中的python數據屬性
- 15. 如何在現有的sqlalchemy模型中使用flask-sqlalchemy?
- 16. 星型模式聚集問題
- 17. 星型模式開始2桌
- 18. 如何設計星型模式
- 19. 數據倉庫 - 星型模式解釋
- 20. 模型按名稱在SQLAlchemy
- 21. SQLAlchemy模型圓形導入
- 22. 掛鉤到sqlalchemy模型
- 23. 執行SQLAlchemy模型定義
- 24. 立方體/表格模型優於關係星型模式
- 25. 在SQLAlchemy模型中使用__slots__
- 26. 在SQLAlchemy中跟蹤模型更改
- 27. 在.NET中加載Elixir/SQLAlchemy模型?
- 28. 動態__tablename__在flask-sqlalchemy模型中
- 29. 在星型模式中我的時間維度表的屬性
- 30. 更新模型的方法:SQLAlchemy的
非常漂亮的設計 - 美麗! – 2012-06-05 12:36:06
受此啓發,我終於想出瞭如何將配置傳遞給declared_attr,以便可以使庫知道主機應用程序模型:https://gist.github.com/miohtama/844cc78bcf1d317e31ca – 2015-06-07 04:07:59