[英]SQLAlchemy find only parents that contain specific children
I have the following many-to-many models:我有以下多对多模型:
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")
How can I get all parents that have the exact children ids in a list (Example: [5,6]) and no additional ids?如何获取所有在列表中具有确切子 ID(例如:[5,6])且没有其他 ID 的父母?
If you have determined the children ids in a subquery, you can make a left join from association table to this subquery and check that the count is correct:如果您已确定子查询中的子 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))
Remark: I think your model needs to be corrected:备注:我认为您的模型需要更正:
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")
I ended up solving it using the following code:我最终使用以下代码解决了它:
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()
But I am pretty sure there must be better ways to do this.但我很确定必须有更好的方法来做到这一点。
If you are using postgresql, the following should work:如果您使用的是 postgresql,以下应该可以工作:
from sqlalchemy.dialects.postgresql import array, array_agg
ids = [c1, c2, c3]
q1 = Parent.query.join(Child)
.group_by(Parent)
.having(
array_agg(Child.id).contains(array(ids)),
count(Child.id) == len(ids)
)
Most probably there will be alternatives for other databases as well.很可能还会有其他数据库的替代品。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.