如何结合SQLAlchemy和EAV DB模式的优点?

时间:2010-08-03 09:52:16

标签: python sqlalchemy pylons entity-attribute-value

我最近一直在与Pylons做一些工作,并且非常喜欢用于数据库交互的SQLAlchemy模型。我的网站有一部分,我认为可以从EAV架构中受益。

将此作为我的表格示例:

id | userid | type   | value
---+--------+--------|------------
1  |  1     |  phone | 111 111 111
---+--------+--------|------------
2  |  1     |  age   | 40

我可以手动运行以下查询来提取和更新数据:

SELECT value FROM table WHERE userid=1 AND type='phone'
UPDATE table SET value=41 WHERE userid=1 AND type='age'

这很容易并且有效...但是手动构建查询不是我的首选方法。我想使用SQLAlchemy来创建我的表模型并让它完成所有的工作。

如果我使用标准架构,其中每个type拥有自己的列,我可以执行以下操作:

class People(Base):

   __tablename__ = 'people'

   id      = Column(Integer, primary_key=True)
   userid  = Column(Integer, ForeignKey('users.id'))
   phone   = Column(Unicode(40))
   age     = Column(Integer)

然后我可以使用以下方法提取数据:

data = Session.query(People).filter_by(id=1).first()
print data.age

我希望能够为我的EAV架构做同样的事情。所以基本上,我需要一种方法来扩展SQLAlchemy并告诉它,当我调用data.age时实际上意味着,我想要SELECT value FROM table WHERE id=1 AND type='age'

这可行吗?或者我是否会被手动发出的查询强迫我的代码混乱?

1 个答案:

答案 0 :(得分:5)

查看vertical attribute mapping的示例。我认为这或多或少都是你所追求的。这些示例提供了类似于dict的接口,而不是示例中的属性(可能更适合任意元数据键,而不是几个特定属性)。

如果您希望单独映射每个属性:可能感兴趣的文档中的内容:

  • sql expressions as mapped attributes:如何将属性映射到任意sql表达式(只读)
  • changing attribute behaviour,尤其是使用描述符和自定义比较器:这归结为只为属性使用普通的python属性,并在get / set +上做任何你需要的事情+可选地规定如何与其他值(查询)进行比较。
  • associationproxy:基本上提供了一个关于关系的简单视图。例如,在您的情况下,您可以使用自定义连接条件(不仅是userid而且还指定类型“age”)使_age与您的KeyValue(或任何您想要调用它)的关系,以及使用uselist=False(因为每个用户只有一个年龄,您需要一个值,而不是列表)。然后,您可以使用age = association_proxy('_age', 'value')使其“仅显示”值,而不是整个KeyValue对象。

我想我会选择基于垂直属性映射示例的东西,或者使用associationproxy /