PhpStormと僕

日々周りを巻き込むことをモットーに。気まぐれでJetBrains製のIDEネタとか書いてます。

Firestoreでselect()を使って特定のフィールドのみ取得する

Firebase Advent Calendar 2019 の18日目です。17日目はlaisoさんの「Cloud FunctionsをGoで書く。またはFirebaseのためのマイクロサービスアーキテクチャ」でした。

今日はFirestoreでselect()を使って、Documentまるごとではなく、特定のフィールドの値のみを取得する方法についてです。 Document内にMapやArrayでそれなりのデータ量を持つことはしばしばあり、また表示側ではそれらは使用しないケースなども多いため、また転送量を節約するために必要なフィールドのみを取得したいということはよくあるニーズかと思います。

RDBMS慣れしている方からするとなにを当たり前のことを、って思われるかもしれませんが、2019-12-17現在Firebaseの firebase-js-sdk 及び Firestore APIでは select() 相当の機能は提供されていません。 つまり、必然的にDocument内の全データを取得することになります。

github.com

ではどうすれば良いのかというと、実はGCP側のFirestoreには .select()APIが提供されていて、StructuredQueryを使って取得することができました。

いつの間にか @google-cloud/firestoreSDKにも .select() のメソッドが追加されていたので、それを使って取得します。

CollectionReference - Documentation

データ例

f:id:rinrin900:20191217182913p:plain

実装

  const snapshot = await firestore
    .collection('posts')
    .where('field1', '==', 'value1')
    .select('title', 'body')
    .get();
  const doc = snapshot.docs[0];

  const data = doc.data();
  console.dir(data);

上記のコード例の場合、field1 が value1 という値の、 title body フィールドの値のみを取得します。 .select() を使用せずにsnapshotからDocumentを取得した場合、Document内の全フィールドが取得されますが、.select() を指定することにより指定したフィールドの値のみで取得することができます。

f:id:rinrin900:20191217183341p:plain


お気づきかとは思いますがこの方法の一番デメリットとして、 @google-cloud/firestore を使う必要があります。

普通にFirebaseを使っている場合は firebase-js-sdk firebase-admin-node を使用しているケースが多いかと思うので、それらと併用することになります。

select()するためだけにGCP側のSDKから毎回引っ張ってくるのも煩雑だし、FirebaseとGCPのFirestore SDK混在したくないというのもあるので、現時点でどうしてもselect()したい時に使える選択肢の1つとして考えておくのが良いかと思います。


明日は @tomoeine さんです、お楽しみに!