SQLAlchemy仅查找包含特定孩子的父母

时间:2020-01-27 20:07:56

标签: python sqlalchemy many-to-many flask-sqlalchemy

我有以下多对多模型:


class Association(db.Model):
    parent_id = db.Column(db.Integer, db.ForeignKey(
        'parent.id'), primary_key=True)
    child_id = db.Column(db.Integer, db.ForeignKey(
        'child.id'), primary_key=True)
    child = db.relationship("Child", back_populates="parents")
    parent = db.relationship("Parent", back_populates="children")


class Parent(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    children = db.relationship("Association", back_populates='parent', 
                               lazy='dynamic', cascade="save-update, merge, delete, delete-orphan")

class Child(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    parents = db.relationship("Association", back_populates='child', 
                              lazy='dynamic', cascade="save-update, merge, delete, delete-orphan")

如何获取列表中具有确切孩子ID(例如[5,6])且没有其他ID的所有父母?

2 个答案:

答案 0 :(得分:1)

如果已确定子查询中的子代ID,则可以从关联表向该子查询进行左连接,并检查计数是否正确:

from sqlalchemy import func, and_

Values = [1 ,3]
childcount = len(Values)
childsquery = db.session.query(Child).filter(Child.id.in_(Values)).subquery()             
resultparents = db.session.query(Association.parent_id).outerjoin(childsquery).group_by(Association.parent_id).having(and_(func.count(Association.parent_id) == childcount, func.count(childsquery.c.id) ==  childcount))

备注:我认为您的模型需要更正:

class Parent(db.Model):
   id = db.Column(db.Integer, primary_key=True)
   children = db.relationship("Association", back_populates='parent', 
            lazy='dynamic', cascade="save-update, merge, delete, delete-orphan")

class Child(db.Model):
   id = db.Column(db.Integer, primary_key=True)
   parents = db.relationship("Association", back_populates='child', 
                          lazy='dynamic', cascade="save-update, merge, delete, delete orphan")

答案 1 :(得分:1)

我最终使用以下代码解决了这个问题:

ids = [c1, c2, c3]
q1 = Parent.query.filter(Parent.children.any(
Association.child_id == c1)).filter(Parent.children.any(Association.child_id == c2))
.filter(Parent.children.any(Association.child_id == c3))
.filter(~Parent.children.any(Association.child_id.notin_(ids)))
.all()

但是我很确定必须有更好的方法来做到这一点。

相关问题