SqlAlchemy加入多对多关系中的条件

时间:2018-02-11 09:38:56

标签: python sqlalchemy

我从前面提到的一个问题中得到了这些表:3个基本模型和2个次要的多对多关系。一个父母可以有一个以上的儿子,不止一个女儿和孩子也可以有多个父母。< / p>

class Parent(db.Model):
 id=db.Column(db.Integer, nullable=False, autoincrement=True, primary_key=True)
 name = db.Column(db.String(45), nullable=False)

 sons= db.relationship('Son',
                       secondary=parent_has_son,
                       back_populates='parents')

 daughters = db.relationship('Daughter',
                           secondary=parent_has_daughter,
                           back_populates='parents')


Class Son(db.Model):
 id=db.Column(db.Integer, nullable=False, autoincrement=True, primary_key=True)
 name = db.Column(db.String(45), nullable=False)
 age = db.Column(db.Integer)
 son_other_col = .Column(db.String(45))

 parents =  db.relationship('Parent',
                           secondary=parent_has_son,
                               back_populates='sons')


Class Daughter(db.Model):
     id=db.Column(db.Integer, nullable=False, autoincrement=True, primary_key=True)
     name = db.Column(db.String(45), nullable=False)
     age = db.Column(db.Integer)
     daughter_other_col1 = .Column(db.String(45))
     daughter_other_col2 = .Column(db.String(45))

     parents =  db.relationship('Parent',
                               secondary=parent_has_daughter,
                               back_populates='daughters')

parent_has_son = db.Table('parent_has_son ', db.metadata,
                                db.Column('parent_id', db.Integer, ForeignKey('Parent.id')),
                                db.Column('son_id', db.Integer, ForeignKey('Son.id')))

parent_has_daughter = db.Table('parent_has_daughter ', db.metadata,
                                    db.Column('parent_id', db.Integer, ForeignKey('Parent.id')),
                                    db.Column('daughter_id', db.Integer, ForeignKey('Daughter.id')))

为了得到父母的儿子或女儿,我可以使用joinload:

parent = db.session.query(Parent).options(joinedload('sons')).filter(Parent.id == 3).first()

然后我可以使用:

sons = parent.sons

但是我不能过滤儿子。例如,如果我想要年龄> 15岁的儿子和年龄> 10岁的女儿,我可以查询:

db.session.query(Parent).options(joinedload('sons')).options(joinedload('daughters')).filter(Paret.id == 3).filter(Son.age > 15).filter(Daughter.age > 10).first()

但问题是,如果没有年龄的儿子&gt; 15岁或女儿,年龄> 10岁,它不会给我任何结果。如果我尝试加入outerjoin,它将返回所有年龄> 15岁和> 10岁的女儿和儿子,即使他们不是父母的儿子和女儿

所以我需要通过条件(年龄)查询父与加入儿子和女儿。如果没有儿子或女儿我需要返回没有孩子的父母或接受这种情况的孩子。

我认为我的问题没有通过eager_loading来解决。 如果我使用contains_eager,我可以查询:

parent = db.session.query(Parent).
join(Parent.sons).options(contains_eager(Parent.sons)).
filter(and_(Parent.id == 3, Son.age > 15)).first()

如果没有年龄的儿子&gt; 15这个查询将返回None,这是我不想要的。

如果我查询:

parent = db.session.query(Parent).
    join(Parent.sons).options(contains_eager(Parent.sons)).
    filter(Son.age > 15).all()

此查询将返回所有年龄> gt的儿子的父母。 15,我不想要。

我需要一个查询,如果他们接受了给定的条件,请给我一个有儿子或女儿的父母。如果我错了,请更正我。

0 个答案:

没有答案