1

MIT の助教授であるすべての教授の名前のリストを取得するために、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ましたが、うまくいきませんでした。

私のエリクサーモデルは次のとおりです。

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: How query with a ManyToMany relationship? とは異なります。つまり、単一の静的なコースではなく、条件を満たすすべてのコースに対して教授をチェックする必要があります。

4

1 に答える 1

0

Elixir が非表示にした中間テーブルを見つけることができますが、完全修飾された列名 ( など__package_path_with_underscores__course_id) を使用していることに注意してください。これを回避するには、次を使用して ManyToMany を定義します。

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_リレーションシップをサポートしていないため、単一のクエリではできません。たとえば、次の 2 つのクエリを使用します。

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

最初のステップでは、アシスタントのリストのリストを作成します。2 番目のステップでは、リストのリストを平坦化し、セットを作成して重複を削除します。

于 2011-06-11T17:51:58.923 に答える