【问题标题】:SQLAlchemy find only parents that contain specific childrenSQLAlchemy 仅查找包含特定子代的父代
【发布时间】:2020-01-27 20:07:56
【问题描述】:

我有以下多对多模型:


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?

【问题讨论】:

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


【解决方案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")

【讨论】:

    【解决方案2】:

    我最终使用以下代码解决了它:

    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()
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-18
      • 1970-01-01
      • 2016-04-20
      • 2013-03-21
      • 2018-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多