web-dev-qa-db-ja.com

TypeORMを使用して多対多の関係をクエリする方法

NoteSubjectと多対多の関係にあります

それを照会する最良の方法は何ですか?私はlikeを指定して、メモのすべての主題を取得します:

  const subjectRepo = connection.getRepository(Subject);
  const response = await subjectRepo.find({
    relations: ['notes'],
    where: { note }
  });

ただし、ノートの件名だけでなく、すべての件名が返されます。

Relnは次のように定義されます:

  @ManyToMany(() => Subject, (subject: Subject) => subject.notes)
  subjects: Subject[];

-と-

  @ManyToMany(() => Note, note => note.subjects)
  @JoinTable()
  notes: Note[];

実行されるクエリは次のとおりです。

SELECT "Subject"."id" AS "Subject_id", "Subject"."name" AS "Subject_name", "Subject"."description" AS "Subject_description", "Subject"."createdDate" AS "Subject_createdDate", "Subject"."updatedDate" AS "Subject_updatedDate", "Subject"."notebookId" AS "Subject_notebookId", "Subject"."measurementsId" AS "Subject_measurementsId", "Subject_notes"."id" AS "Subject_notes_id", "Subject_notes"."content" AS "Subject_notes_content", "Subject_notes"."notedAt" AS "Subject_notes_notedAt", "Subject_notes"."createdDate" AS "Subject_notes_createdDate", "Subject_notes"."updatedDate" AS "Subject_notes_updatedDate", "Subject_notes"."notebookId" AS "Subject_notes_notebookId" FROM "subject" "Subject" LEFT JOIN "subject_notes_note" "Subject_Subject_notes" ON "Subject_Subject_notes"."subjectId"="Subject"."id" LEFT JOIN "note" "Subject_notes" ON "Subject_notes"."id"="Subject_Subject_notes"."noteId"

注:これを行うことができます:

  return subjectRepo
    .createQueryBuilder('subject')
    .leftJoin('subject.notes', 'note')
    .where('note.id = :id', { id: note.id })
    .getMany();

しかし、私は文字列を減らし、明示的に参加するアプローチを望んでいます

14
Jonathan

TypeORMで生成しようとしているSQLは、おおよそ次のとおりです。

_SELECT *
FROM subject
JOIN subject_note AS jt on jt.subject_id = subject.id
WHERE jt.note_id = :id
_

1.これは_repo.find_では不可能です

執筆時点では、repo.find(...)を使用して結合テーブルにwhere句を作成する方法はありません。 joindoc )できますが、where句はリポジトリのエンティティにのみ影響します。

TypeORMも無効なwhere句を暗黙的に無視するので、それらに注意してください。

2.ノートエンティティを再選択します

特定のsubjectのすべてのnoteが必要な場合は、前述のようにクエリビルダーを使用するか、ノートオブジェクトとその関係を再選択する必要があります。

_note = await noteRepo.find({
    relations: ['subjects'],
    where: { id: note.id }
});
const subjects = note.subjects
_

3. TypeORM遅延関係を使用する

再選択を避けたい場合は TypeORM Lazy relations を使用する必要がありますが、これにより両方のエンティティのタイプをPromiseに変更する必要があります

_// note entity
@ManyToMany(() => Subject, (subject: Subject) => subject.notes)
subjects: Promise<Subject[]>;

// subject entity
@ManyToMany(() => Note, note => note.subjects)
@JoinTable()
notes: Promise<Note[]>;
_

このレイジーリレーションでは、リンクされたノートを使用する前にawaitをロードする必要がありますが、findメソッドにリレーションの配列を提供する必要はありません。

_const note = await noteRepo.find({
    where: { id: someId }
});
const subjects = await note.subjects
_
20