我想询问一个具备所有要求技能的人。不确定什么是动态构建查询的最佳方式。
ORM对象如下。人与技能之间的多对多,此处不包括连接表:
Person
name=John, skills=[Skill(id=1)] # John knows Python
name=Eve, skills=[Skill(id=1), Skill(id=2)] # Eve knows Python and SQLAlchemy
Skill
id=1, name=Python
id=2, name=SQLAlchemy
id=3, name=Social skills
在搜索页面上,用户选择一项或多项技能,并基于此创建人员的搜索结果。假设用户希望找到一个了解Python和SQLAlchemy的人。Application从表单submit中获取两个id的列表,[1,2]。我得到了以下关于工作类型的查询,以查找具有匹配技能的人员:
session.query(Person)./
join(Skill, Person.skills).filter(Skill.id.in_(list_of_skill_ids))
但是,使用in_u子句会导致发现John person,因为他具有所需的技能之一。但是搜索结果应该只显示那些具备所需技能的人。基本上,我想要的是类似于in_u()的东西,但是是哪个用户,而不是或匹配id列表。我可能应该用这个替换in_u()部分,它不直接接受id列表:
filter(Person.id == 1, Person.id == 2)
但是,使用从表单接收的技能ID列表以编程方式构建查询的最简单方法是什么?id的数目可以是1..n。或者这是按其子级查询父级的正确方法吗?
最佳答案
最直接的SA解决方案是对每个技能使用any
:
list_of_skill_ids = [1, 2]
qry = session.query(Person)
for skill_id in list_of_skill_ids:
qry = qry.filter(Person.skills.any(Skill.id == skill_id))
print('\n'.join("{}".format(_) for _ in qry.all()))
对于大型数据集来说,这可能不是性能最好的查询,但它非常干净。
或者下面也应该有用。(类似于RedBaron的回答,但直接将检查放入查询中):
qry = (session.query(Person)
.join(Skill, Person.skills)
.filter(Skill.id.in_(list_of_skill_ids))
.group_by(Person)
.having(len(list_of_skill_ids) <= func.count(Skill.id))
)
print('\n'.join("{}".format(_) for _ in qry.all()))
关于python - SQLAlchemy-通过子项查询父项,过滤联接以匹配列表中的每个子项,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23815830/