4
3

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 3 years have passed since last update.

Firestore データ取得の制限について

Posted at

概要

  • 普段大変お世話になっているFirestoreですが、DBから直接データを取得しようとすると、制限があるので自分なりにまとめました。
  • 今回は下記の様な例で説明していきたいと思います。6人の男の子の身長と体重が入ったDBです。

collection名:boys

id name height weight
0 一郎 160 60
1 二郎 165 65
2 三郎 170 70
3 四郎 175 75
4 五郎 180 80
5 六郎 185 85

orderByの制限

不等号を使った複数フィールドの絞り込みができない

  • 例のデータだと、例えば、身長160cm~170cmかつ、体重65kg~80kgの人、みたいな絞り込みが仕様上できません。
  let boysRef = db.collection("boys").where("height", ">=", 160).where("height", "<=", 170).where("weight", ">=", 65).where("weight", "<=", 80); 
  let items = await boysRef.get(); // エラー
  • 出てくるエラーはこんな感じ。不等号を含むwhereフィルターは全て同じフィールドに対しての指定である必要がありますみたいに言われます。
  • 今回の例でいうと、身長160cm~170cmの人、体重65kg~80kgの人、どっちか片方だけの絞り込みはできます。
Uncaught (in promise) FirebaseError: Invalid query. All where filters with an inequality (<, <=, !=, not-in, >, or >=) must be on the same field. But you have inequality filters on 'height' and 'weight'

不等号をつかった絞り込みと、orderByに異なるフィールドを指定できない

  • 今回の例だと、例えば、身長160cm~170cmの人に絞り込みつつ、体重を降順に並び替える、というのができません。
  let boysRef = db.collection("boys").where("height", ">=", 160).where("height", "<=", 170).orderBy("weight", "desc");
  let items = await boysRef.get(); // エラー
  • こんなエラーです。不等号を含むwhereフィルターはheightについてのものなので、最初のorderByのフィルターも、heightについて指定する必要がありますということでした。
Uncaught (in promise) FirebaseError: Invalid query. You have a where filter with an inequality (<, <=, !=, not-in, >, or >=) on field 'height' and so you must also use 'height' as your first argument to Query.orderBy(), but your first orderBy() is on field 'weight' instead.
  • ちなみに、2個目のorderByにweightを指定する↓のやり方だとエラーはでませんが、身長順で並び替えたあと、同順位のデータを体重順で並び替えるだけなので、期待する結果は得られません。
  let boysRef = db.collection("boys").where("height", ">=", 160).where("height", "<=", 170).orderBy("height", "desc").orderBy("weight", "desc");
  let items = await boysRef.get();

ページネーションが実現しづらい

  • まずfirestoreを使ってのページングにはstartAfterを使います。上の例だと以下の通りです。
  let boysRef = db.collection("boys").orderBy("height", "asc").limit(2);
  let items = await boysRef.get(); // itemsには一郎、二郎のデータ
  let last = items[items.length - 1];
  let nextItems = boysRef.startAfter(last.doc).get(); // 三郎、四郎のデータ
  • 上記のやり方だともっと見る形式の追加ローディングにはさくっと対応できますが、googleの検索結果ページにある様なページネーションには対応が困難です。
  • 例えば、100件データがあるうちの51件目から表示したい場合、一発で51件目のデータを特定することが、startAfterでは不可能です。

参考リンク

4
3
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
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?