在sqlalchemy中,我为我的数据库定义了一个模型,在这种情况下,两个表“sample”和“experiment”,它们通过多对多关系相互链接:
class Sample(Base):
__tablename__ = 'sample'
id = Column(Integer, primary_key=True)
name = Column(String)
date = Column(String)
class Experiment(Base):
__tablename__ = 'experiment'
id = Column(Integer, primary_key=True)
name = Column(String)
description = Column(String)
result = Column(String)
samples = relationship('Sample', secondary='sample_has_experiment', backref="experiments")
t_sample_has_experiment = Table(
'sample_has_experiment', metadata,
Column('sample_id', ForeignKey('sample.id'), primary_key=True, nullable=False, index=True),
Column('experiment_id', ForeignKey('experiment.id'), primary_key=True, nullable=False, index=True)
)
在我的数据库中,我有一个样本“达丽星”,在实验中有两个实验“冷融合”和“蠕虫洞”。
我尝试通过连接到样本表来查询“蠕虫洞”实验:
samples = s.query(Obj.Sample).join(Obj.Sample.experiments).\
filter(Obj.Experiment.name == "Worm hole").all()
for sample in samples:
for experiment in sample.experiments:
print(experiment.name)
但结果我仍然得到了两个实验“蠕虫洞”和“冷融合”。所以看起来似乎没有应用过滤。如何过滤我只收到“蠕虫洞”实验对象的方式?谢谢。
@Dublicate:确实它看起来像是同一个问题,但是给出的答案并没有解决我的问题。在我看来,我建议的查询与提议的答案完全一样。
答案 0 :(得分:1)
您的代码所说的是:
对于所有属于虫洞实验的样本
也就是说,给定一个特定样本,sample.experiments
始终是样本所属的所有实验,而不仅仅是您通过该样本进行的实验。
如果你要添加一个不属于虫洞实验的新样本,你可以看到这个。它不应出现在您的查询中。
所以,我的回答是"为什么我的查询不会对连接进行过滤,"是我强烈怀疑它是。
如果您想要虫洞实验中的样本对象,那么
samples = session.query(Experiments).filter_by(name = 'wormhole').one().samples
答案 1 :(得分:0)
编辑:其实我第一次意识到我的错误是什么。我必须查询所有表,然后应用连接和过滤器:
qry = s.query(Obj.Sample, Obj.Experiment).\ # Query both tables!
filter(Obj.Sample.name == "...").\
filter(Obj.Experiment.name == "...").\
join(Obj.Experiment, Obj.Sample.experiments).all()
替代方法:使用子查询会产生所需的行为:
wormhole_exp = s.query(Obj.Experiment).filter(Obj.Experiment.name == "wormhole").subquery()
print(s.query(Obj.Sample, wormhole_exp).join(wormhole_exp, Obj.Sample.experiments).one())