firestoreでN:N
firestore で N:N (many to many) のデータを表現する方法
例として、生徒が履修している授業を保存する DB を考える
Reciprocal
生徒 DB に履修した講義を入れる
コース DB に履修した生徒を入れる
https://scrapbox.io/files/6092088f1cc847001ca9c7ee.png
構成
students (C)
uid (D)
name
...
courses (C)
courseId (D)
courses (C)
courseId (D)
title
...
students (C)
uid (D)
読み込み
生徒が N の講義を登録していた場合、ある生徒が履修している講義一覧 + ある講義を履修している生徒一覧 = 2N の読み取りが発生する
書き込み
履修の変更があったときに生徒 DB と講義 DB の2つを変更する必要がある
batch write を使えば軽量になる
code:js
async function attendCourse(studentId, courseId) {
const attendingRef = db.doc(students/${studentId}/attending/${courseId});
const attendeeRef = db.doc(courses/${courseId}/attendees/${studentId});
const batch = db.batch();
batch.set(attendingRef, {});
batch.set(attendeeRef, {});
await batch.commit();
}
ユーザが信用できない場合、セキュリティが高く書き込めない場合は cloud functions を使用
セキュリティルール
写経になってしまうのでリンク参照
Junction
A が a という講義を登録した、という関係性を保存する新たな DB を用意する
https://scrapbox.io/files/60920a3741491b001cdf9a3a.png
構成
students (C)
uid (D)
name
...
courses (C)
courseId (D)
title
...
junctions_student_and_course (C)
uid_courseId (D)
studentId
courseId
junctions_student_and_course は <student uid> と <course uid> を結合したもの
読み込み
2N
junction を検索 + course を検索
これは M + N では?
セキュリティルールが機能しないためフィルタを使う
code:js
async function fetchCourses(studentId) {
const junctions = await db
.collection(junction_student_course)
.where("studentId", "==", studentId)
.get();
const courses = await Promise.all(
junctions.docs
.filter(doc => doc.exists)
.map(doc => db.doc(courses/${doc.data().courseId}).get())
);
return courses.filter(doc => doc.exists).map(doc => ({ id: doc.id, ...doc.data() }));
}
これだとクライアントサイドでコードを書き換えられるのでは…?
code:js
match /junction_student_course/{junctionId} {
allow read:
if request.auth != null
&& request.auth.uid == resource.data.studentId;
allow create:
if request.auth != null
&& request.auth.uid == request.resource.data.studentId
&& junctionId == request.auth.uid + "_" + request.resource.data.courseId;
こんな感じでセキュリティルールを組める
ただ誰がどの講義を履修したのかはばれる
書き込み
履修の変更は jucntions のドキュメントを削除するだけでよい
比較
パフォーマンス
読み込み
どちらも大差ない
書き込み
reration
2回
junction
1回
メンテナンス性
jucntion の方が関係性を持つという責任を分轄しており、メンテナンス性が高い
reration だど生徒 DB 講義 DB で履修情報を同期させる必要がある
セキュリティ
どちらも大差ない