使用以下映射集合设置,使用字典语法将Person与任何数量的属性映射到另一个表中进行访问:
class FormField(Model):
id = Column(Integer, primary_key=True)
person_id = Column(Integer, ForeignKey('person.id'), nullable=False)
keyword = Column(String(255))
payload = Column(Text)
class Person(Model):
id = Column(Integer, primary_key=True)
name = Column(String(255))
fields = relationship("FormField",
collection_class=attribute_mapped_collection('keyword'),
cascade="all, delete-orphan")
正常用法(另见文档http://docs.sqlalchemy.org/en/latest/orm/collections.html#dictionary-collections):
person = Person()
person.fields["mykey"] = FormField("mykey", "Some payload")
搜索具有特定属性值的人员也非常简单。但问题是,如何搜索根本没有属性的人,特别是作为更复杂查询的一部分?
一种方法可能是始终创建所有属性并将NULL放入有效负载中,但是否可以有效搜索完全缺失的属性?例如,如果查询应该挖出那些具有干扰性的人。有价值" A",属性" b"有价值" B"和缺少属性" c"?
db.session.query(Person).join(FormField).join(FormField_alias)
.filter(FormField.keyword == "a", FormField.payload == "A")
.filter(FormField_alias.keyword == "b", FormField_alias.payload == "B")
# ???
.all()
我猜,它不像添加一个过滤器那么简单。那么呢?
答案 0 :(得分:1)
您可以使用一堆EXISTS expressions而不是内部联接:
In [48]: session.query(Person).\
...: filter(Person.fields.any(and_(FormField.keyword == 'a',
...: FormField.payload == 'A')),
...: Person.fields.any(and_(FormField.keyword == 'b',
...: FormField.payload == 'B')),
...: not_(Person.fields.any(FormField.keyword == 'c'))).\
...: all()
例如在Postgresql中,EXISTS和NOT EXISTS产生的半连接和反连接应该通过适当的索引充分有效。