[Vue.js & Firebase]collectionGroupを使って柔軟にデータ取得する方法[Cloud Firestore]

firestoreから柔軟に情報を取得して、あなたのWebアプリ制作に役立てましょう

Firestore から柔軟にデータを取得したい、そんな時に。

Firestore から情報を取得する方法は多数あります。
しかも、その取得方法はとても柔軟で、
「この特定の document を取得したい」
「この子階層の、特定の条件に一致した collection を取得したい」
「配列として値を持たせたフィールドを対象に、複数の document を横断して検索、一致した値を持つデータを取得したい」
といった事がスムーズに実現できます。

今回はそれらのデータ取得方法について、いくつかご紹介できればと思います。

今回も、例として、Vue.js と Firebase を組み合わせて使用していると仮定して、以下に記載していきます。
Vue.js 以外のフロントエンドフレームワークを使用されている方は、適宜そのフレームワークの記法に置き換えてください。
(前回同様 .vue ファイルの、 mounted: 内に記述することを想定しています。)

document や collection を指定してデータを取得

まずはオーソドックスな方法。基本形です。
文字通り、document, collection を指定して情報を取得します。

const db = firebase.firestore();

// collection 'foo' を参照
const sampleColRef = db.collection('foo');

// collection 'foo' にある document 'bar' を参照
const sampleDocRef = db.collection('foo').doc('bar');

上記のように指定して参照を作り、

const me = this;
let dataValue;

sampleColRef.onSnapshot((snapshot) => {
  me.args = [];
  snapshot.forEach((doc) => {
    dataValue = doc.data();
    me.args.push({
      key: doc.id,
      value: dataValue
    });
  });
});

例えば上記のようにして取得したデータを、
vue.js 側では v-for で展開するなどすれば、コンテンツで使用できるわけです。
( vue.js & Firebase での制作を経験のある方ならご存知の部分かと思いますが )

where() を使って「条件を指定」したデータを取得

const db = firebase.firestore();
const sampleRef = db.collection('foo').where('bar', '==', true);

こちらの例は、「条件の指定」です。
collection ‘foo’ に存在する、’bar’ というフィールドを持つデータを取得する、という意味になります。

where() を使用すると、条件を加えた上で、その条件に一致するデータのみを取得する事ができます。

ここまでに挙げた取得方法は、公式の以下の部分で解説されていますので、一読する事をおすすめします。
単純なクエリ – Cloud Firestore で単純なクエリと複合クエリを実行する

とても強力な collectionGroup()

const db = firebase.firestore();
const Reference = db.collectionGroup('foo').orderBy('time','desc').where('bar', 'array-contains', this.mydata);

今回、最もご紹介したかったのはこちらです。
例えば、孫階層に foo という名前を持つ collection が複数存在していたとします。
子階層には複数の document が存在しているけど、それら全てを特定の条件で検索して、データを取得したい。
そんな時に使えるのが collectionGroup() です。(もちろん collectionGroup() の用途は他にも多々あるかと思いますが、たとえとしての一例です)

上記の例では foo という名前を持つ孫階層の collection から、
time というフィールドを基準にして、順番を desc でソート。
さらに、where() を使用して
bar というフィールド( 配列として格納されている想定 )の値の中から、
this.mydata に一致するデータのみ
を取得しようとしています。

これを実行する際には以下、公式にも記載のあるように、
Firestore においての「複合クエリ」というものを使用することにあたりますので、
事前に「複合インデックス」を作っておく必要があります。
複合クエリ – Cloud Firestore で単純なクエリと複合クエリを実行する

「複合インデックス」を作っておく」とは…?

「事前に複合インデックスを作っておく」、というと難しく聞こえるかもしれませんが、心配いりません。

実はこちら、指定した参照先から「複合クエリ」を使ってデータを取得しようとした時に、
まだ該当箇所に「複合インデックス」が存在しない場合は、
Firestore が自動で
「今あなたが取得しようとしたことは、複合インデックスを作れば実現できますよ」と、デベロッパーツール上にて、ちゃんと教えてくれます。

この部分、Firestore公式の以下ページにも言及されていました。
不足しているインデックスをエラー メッセージから作成する – Cloud Firestore でのインデックス管理

上記の公式の解説の中にある、

既存のインデックスに対応しない range 句で複合クエリを実行すると、エラーが発生します。このエラー メッセージに含まれている Firebase コンソールのリンクを使用すると、不足しているインデックスを作成できます。

という部分が重要なのですが、こちらは
まだ存在しない「複合インデックス」を使おうとした際に Chrome のデベロッパーツールを開くと、該当のエラーメッセージを確認する事ができます。

「複合クエリ」を作れば実現できると教えてくれます

上記のキャプチャにあるように、

‘Uncaught Error in onSnapshot: FirebaseError: The query requires a COLLECTION_GROUP_DESC index for collection sample and field time. You can create it here: https://console.firebase.google…’

と Chrome のデベロッパーツール上でエラーメッセージとして教えてくれまして、この意味としては

クエリには、コレクション’sample’とフィールド’time’の「COLLECTION_GROUP_DESCインデックス」が必要です。ここで作成できます:https://console.firebase.google ….

といった内容になります。

デベロッパーツール上の指示どおりに、
「 You can create it here: 」
に続くURLを、そのままデベロッパーツール上からリンクをクリックして進むと、
Cloud Firestore のコンソール内、インデックス作成ページ ( /firestore/indexes ) に遷移します。

遷移後に出てくるダイアログを確認すれば、
Firestore が自動で必要な複合インデックスを作成してくれます。

複合インデックスの作成時は少し時間がかかるのですが
ここまで自動でスムーズにやってくれる Firestore には、本当に感謝です。
(以前、作成した時の体感では5分~ほどかかります。指定する条件によって所要時間は異なると思います)

一度、「複合インデックス」の生成が済んでしまえば、「複合クエリ」によるデータの取得が使用可能になります。
つまり、このセクションの冒頭でご紹介したような、
以下のような条件(複合クエリ)による投稿の取得ができるようになる、という事です。

const db = firebase.firestore();
const Reference = db.collectionGroup('foo').orderBy('time','desc').where('bar', 'array-contains', this.mydata);

(前回も言いましたが)Firebase は Google が提供している強力なプラットフォーム

最近、とても Vue.js & Firebase を使った制作が快適です。
特に Cloud Firestore に移行してから、その便利さ、フレキシブルさにいつも感謝しています。
(実は結構ながい期間、 RealtimeDatabase を使って制作を続けていまして、ようやく少し前のプロジェクトから、重い腰を上げて Cloud Firestore での制作に移行した経緯があるのですが…
Cloud Firestore の使いやすさには本当に感動しました。本当に、もっと早く移行していれば良かった!)

シングルページアプリケーションやPWA(Progressive Web Apps)を制作する際などに、大活躍してくれる存在、Firebase
今回は、そのFirebaseプロダクトの中に存在する、Cloud Firestore から、情報を取得する複数の方法について、その例をご紹介しました。
当サイトでは今後も、Firebase や Vue.js に関する記事を更新していく予定です。

※この記事は随時、内容の修正、更新を行う可能性があります。