1

我正在尝试构建一个 sqlalchemy 查询来获取麻省理工学院助理教授的所有教授的姓名列表。请注意,可以有多个助理教授与某个课程相关联。

我正在尝试做的大致相当于:

uni_mit = University.get_by(name='MIT')
s = select([Professor.name],
           and_(Professor.in_(Course.assistants),
                Course.university = uni_mit))
session.execute(s)

这不起作用,因为in_只为实体的字段定义,而不是为整个实体定义.. 不能Professor.id.in_用作 Course.assistants 是教授列表,而不是他们的 ID 列表。我也试过contains,但我也没有工作。

我的 Elixir 模型是:

class Course(Entity):
    id = Field(Integer, primary_key=True)
    assistants = ManyToMany('Professor', inverse='courses_assisted', ondelete='cascade')
    university = ManyToOne('University')
    ..

class Professor(Entity):
    id = Field(Integer, primary_key=True)
    name = Field(String(50), required=True)
    courses_assisted = ManyToMany('Course', inverse='assistants', ondelete='cascade')
    ..

如果我可以访问中间的多对多实体,这将是微不足道的(条件是and_(interm_table.prof_id = Professor.id, interm_table.course = Course.id),但 SQLAlchemy 显然对我隐藏了这个表。

我正在使用 Elixir 0.7 和 SQLAlchemy 0.6。

顺便说一句:这个问题与Sqlalchemy+elixir 不同:如何使用 ManyToMany 关系进行查询?因为我需要根据所有满足条件的课程而不是单一的静态课程来检查教授。

4

1 回答 1

0

您可以找到 Elixir 隐藏的中间表,但请注意它使用完全限定的列名(例如__package_path_with_underscores__course_id)。为避免这种情况,请使用例如定义您的多对多

class Course(Entity):
    ...
    assistants = ManyToMany('Professor', inverse='courses_assisted',
                            local_colname='course_id', remote_colname='prof_id',
                            ondelete='cascade')

然后您可以使用访问中间表

rel = Course._descriptor.find_relationship('assistants')
assert rel
table = rel.table

table.c.prof_id并且可以使用等访问列。

更新:当然,您可以在更高级别执行此操作,但不能在单个查询中执行此操作,因为 SQLAlchemy 尚不支持in_关系。例如,有两个查询:

>>> mit_courses = set(Course.query.join(
... University).filter(University.name == 'MIT'))
>>> [p.name for p in Professor.query if set(
... p.courses_assisted).intersection(mit_courses)]

或者,或者:

>>> plist = [c.assistants for c in Course.query.join(
... University).filter(University.name == 'MIT')]
>>> [p.name for p in set(itertools.chain(*plist))]

第一步创建助手列表。第二步将列表列表展平,并通过制作集合来删除重复项。

于 2011-06-11T17:51:58.923 回答