Python 使用“不包含”一对多筛选SQLAlchemy
我试图查询和过滤一对多的关系,但似乎不知道如何做到这一点 以下是为简洁起见修剪的映射:Python 使用“不包含”一对多筛选SQLAlchemy,python,sqlalchemy,Python,Sqlalchemy,我试图查询和过滤一对多的关系,但似乎不知道如何做到这一点 以下是为简洁起见修剪的映射: class Bug(Base): __tablename__ = 'bug' id = Column('bug_id', Integer, primary_key=True) tags = relationship('Tag', backref='bug') class Tag(Base): id = Column('tag_id', Integer, primary_key
class Bug(Base):
__tablename__ = 'bug'
id = Column('bug_id', Integer, primary_key=True)
tags = relationship('Tag', backref='bug')
class Tag(Base):
id = Column('tag_id', Integer, primary_key=True)
name = Column('tag_name', String)
bug_id = Column('bug_id', ForeignKey('bug.bug_id'))
我希望能够找到所有没有名为foo的标记的Bug。我不确定标记表应该为您表示什么,但奇怪的是,您的模式将每个标记与一个Bug关联起来。如果您想用相同名称的标记标记多个bug,您将在标记类中创建多个同名行。这似乎违反了法律 在数据库中描述标记云的标准方法是使用多对多关系和二级关联表,二级关联表关联bug、标记对。SQLAlchemy文档有一个 如果您坚持按原样使用模式,有几种方法可以做到这一点 客户端过滤 这显然效率低下,但很容易理解。一个接一个地检查bug,一个接一个地检查它们的标记,并消除tag.name==foo: 两个问题 找到所有标记为foo的不同bug,然后找到该集合的补充 此版本正好使用数据库的两个查询:
foo_bugs = [t.bug_id for t in session.query(Tag).filter_by(name="foo").distinct()]
session.query(Bug).filter(~Bug.id.in_(foo_bugs))
带子查询的一个查询
与上面相同,但将foo_bug设为子查询,因为没有理由在客户端获取其内容:
foo_bugs = session.query(Tag.bug_id).filter_by(name="foo").distinct().subquery()
session.query(Bug).filter(~Bug.id.in_(foo_bugs))
这将是一个不相关的子查询,因此从服务器的角度来看,它应该像两个单独的查询一样进行优化。我不确定标记表应该为您表示什么,但奇怪的是,您的模式将每个标记与一个Bug相关联。如果您想用相同名称的标记标记多个bug,您将在标记类中创建多个同名行。这似乎违反了法律 在数据库中描述标记云的标准方法是使用多对多关系和二级关联表,二级关联表关联bug、标记对。SQLAlchemy文档有一个 如果您坚持按原样使用模式,有几种方法可以做到这一点 客户端过滤 这显然效率低下,但很容易理解。一个接一个地检查bug,一个接一个地检查它们的标记,并消除tag.name==foo: 两个问题 找到所有标记为foo的不同bug,然后找到该集合的补充 此版本正好使用数据库的两个查询:
foo_bugs = [t.bug_id for t in session.query(Tag).filter_by(name="foo").distinct()]
session.query(Bug).filter(~Bug.id.in_(foo_bugs))
带子查询的一个查询
与上面相同,但将foo_bug设为子查询,因为没有理由在客户端获取其内容:
foo_bugs = session.query(Tag.bug_id).filter_by(name="foo").distinct().subquery()
session.query(Bug).filter(~Bug.id.in_(foo_bugs))
这将是一个不相关的子查询,因此从服务器的角度来看,它应该像两个单独的查询一样进行优化。您可以在关系上使用any操作符
bugs_without_foo = session.query(Bug).filter(
db.not_(Bug.tags.any(Tag.name == 'foo'))
).all()
它看起来更好,但它比Dan Lenski答案中的子查询要好。您可以在关系上使用any操作符
bugs_without_foo = session.query(Bug).filter(
db.not_(Bug.tags.any(Tag.name == 'foo'))
).all()
它看起来更好,但它比Dan Lenski答案中的子查询要好。您对数据映射错误的评估是正确的。实际上,我正在映射一个我拥有只读访问权限的现有数据库结构,所以我正在处理我所拥有的。感谢您提供完整的答案和多个选项!您对错误数据映射方式的评估是正确的。实际上,我正在映射一个我拥有只读访问权限的现有数据库结构,所以我正在处理我所拥有的。感谢您提供完整的答案和多个选项!