我最近一直在用 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 '
.
这可行吗?还是我会被迫用手动发出的查询来打乱我的代码?
最佳答案
查看 vertical attribute mapping 的示例.我认为这或多或少是你所追求的。这些示例提供了一个类似 dict 的界面,而不是您示例中的属性(对于任意元数据键可能更好,而不是一些特定的属性)。
如果您更愿意单独映射每个属性:文档中可能感兴趣的内容:
- sql expressions as mapped attributes : 如何确实可以将属性映射到任意 sql 表达式(只读)
- changing attribute behaviour , 特别是使用描述符和自定义比较器:这归结为只为您的属性使用普通的 Python 属性,并在 get/set 上做任何您需要的事情 + 可选地规定与其他值(用于查询)的比较需要如何工作。
- associationproxy : 基本上提供了一个更简单的关系 View 。例如,在您的情况下,您可以使用自定义连接条件(不仅是用户 ID,还指定类型“年龄” ),并使用
uselist=False
(因为每个用户只有一个年龄,所以您需要一个值,而不是列表)。然后,您可以使用age = association_proxy('_age', 'value')
使其仅“显示”值,而不是整个 KeyValue 对象。
我想我会选择基于垂直属性映射示例的东西,或者使用 associationproxy/
关于python - 我如何结合 SQLAlchemy 和 EAV DB 模式的优势?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3395355/