10
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

FirestoreのSubCollectionに対してQueryが使えない問題にどう立ち向かうか

Posted at

Firestore、便利ですよねぇ。
ただ、2018/03執筆時点ではまだβなので荒削りだったり要件満たしにくい部分でつらいなぁっていう部分はいくつかあります。

その1つが表題の件の「SubCollectionにQueryが使えない」問題。
どういうことかというと、例えば「CDごとに曲名とその曲番号(連番)を保持する」構造を例に考えてみます。

- albums [collection]
    - title
    - musics [collection]
        - title
        - songNumber

Firestoreでどう表現するかというと、disksっていうCollectionを作って、その中にSubCollectionとしてmusicsを持つ形が一番シンプルに見えます。

20180309180400.png

こんなイメージ。ただ、この構造の場合は表題の制限があり、musics内のデータを直に参照したいケース、
具体的には「ユーザ属性は曲のタイトルを持っているが、その曲がどのアルバムに属しているか分からない(紐付けることができない)」時に、sounds内のデータを特定することができません。
この件についてStackOverFlowでGoogleエンジニアが「Collection group queryという機能で提供する予定だが、提供はすぐではない」という回答をしています。

ObjectやArrayとして下位データを持つ方法もなくはないですが、そもそものSubCollectionのメリットを活かせないのではここでは考慮から外しつつ、
Collectionであることメリットを活かし現時点で解決できるパターンをいくつか見ていきます。

親CollectionにSubCollectionのキー一覧を持つ方法

親のCollection側に、soundsのキー一覧を持つのが一案としてあります。

image.png

soundKeys: [
    "1. 主よ,人の望みの喜びよ(In 4 Mix)"
    "2. 眠れる森~Sleeping Forest",
    "3. Mouring The Passing Time"
]

キー一覧を持つ際、上記のようにFirestore内のデータとして配列で持ちたくなります。
が、Queryでwhere in句のように配列を対象に検索することができないので、以下のようなObject形式で持つ必要があります。

soundKeys: {
    "1. 主よ,人の望みの喜びよ(In 4 Mix)": true,
    "2. 眠れる森~Sleeping Forest": true,
    "3. Mouring The Passing Time": true
}

sound側のkeyを持っている状態からこのalbums -> soundsのdocを取得する場合には

const userPlayingTitle = '2. 眠れる森~Sleeping Forest'
const querySnapshot = await db.collection('albums')
    .where(`albums.${userPlayingTitle}`, '==', true).get()
...

というような形でquerySnapshotを持ってくることができるようになりました。

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?