我想询问一个具备所有要求技能的人。不确定什么是动态构建查询的最佳方式。
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/

10-12 22:11
查看更多