2018-10-18に更新

Firestoreの参照型によるリレーションを試す

FirebaseのFirestoreはNoSQLのため、コレクションの下にサブコレクションを登録するような形でデータをネストして登録していくことができます。ただ、これではRDBでやっているようなリレーションが実装できず、データが色々なところに分散してしまうため、各データを連携させる必要がある場合には非常に使いづらいです。一応リレーションもできるっぽいので、ちょっと試してみました。

※2018/8月現在、Firestoreがβバージョンのタイミングの記事となります。環境はJavaScriptです。

ちなみに、もうちょっと詳しく考察されている記事があります。

Cloud FirestoreのSubCollectionとQueryっていつ使うの問題

多分これのリレーションシップ参照型というところの話です。上記の記事ではManyToMany, hasManyあたりの話をしていると思いますが、今回試したのはbelongsToの話になります。

参照型

Firestoreに格納するデータには色々型があります。

https://firebase.google.com/docs/firestore/manage-data/data-types?hl=ja

この中を見ると「参照」という型があります。が、概念的なものが書かれているだけで、他のページを探してみても説明が見つかりません。(ただ見つけられていないだけか、βだからかは分かりません)

そのためとりあえずこれを使って1:1のリレーションができるか試してみました。

そもそも参照型と何か

データを追加するところのマニュアルを見てみると、addした後にdocRefという値が取得できています。もしかするとこれかな? と思い、別のデータを保存する際にこのdocRefをそのまま代入して保存してみました。

      // userのdocRefをそのまま入れる 
      this.post.user = this.$store.state.user;
      db
        .collection("posts")
        .add(this.post)
        .then(docRef => {
          this.posts = getPosts();
        })
        .catch(error => console.log(error));

Firebaseのconsoleで見てみるとちゃんと入っていました。

body: "aaaa"
user: /users/scQa34jZbdF2mpuVcMMV

という感じで、参照型の保存自体はこんな感じでできるようです。

リレーションデータの取得

~~取得までは試していません。~~

ざっと1ファイルで適当に試してみました。適当なので実際に組み込む時は並列処理したりもっと良い書き方ができると思います。

const firebase = require("firebase");

const config = {
};
firebase.initializeApp(config);
const db = firebase.firestore();

async function execute() {
  // ユーザーデータを登録
  const userData = {
    name: "name" + (new Date()).getTime(),
  };
  const userRef = await db.collection("users").add(userData);

  // ユーザーデータを紐づけて投稿を登録
  const postData = {
    name: "post" + (new Date()).getTime(),
    user: userRef
  };
  const postRef = await db.collection("posts").add(postData);

  // 登録したデータを全部取得
  const querySnapshot = await db.collection("posts").get();
  const posts = [];
  querySnapshot.forEach(doc => {
    posts.push(doc.data());
  });

  for (let i = 0; i < posts.length; i++) {
    // リレーションデータを取得
    const post = posts[i];
    const userQuerySnapshot = await post.user.get();
    post.userData = userQuerySnapshot.data();
  }

  return posts;
}

execute().then(posts => {
  console.log(posts);
  process.exit(0);
});

とりあえず試しに動かしたサンプルも置いておきます。

Firestore Reference data type sample


dala00

Crieitの開発者です。 主にLAMPで開発しているWebエンジニアです(在宅)。大体10年程。 業務依頼、同業種の方からのコンタクトなどお気軽にご連絡ください。 業務経験有:PHP, MySQL, Laravel5, CakePHP3, JavaScript, RoR 趣味:Elixir, Phoenix, Node, Nuxt, Express, Vue等色々

Crieitはαバージョンで開発中です。進捗は公式Twitterアカウントをフォローして確認してください。 興味がある方は是非記事の投稿もお願いします! どんな軽い内容でも嬉しいです。
なぜCrieitを作ろうと思ったか
関連記事

コメント