masalib.hatenablog.com の補足記事になります
データ取得を色々試してみた結果になります。
- whereとorderbyの関係について
- whereとorderbyのカラムが違う場合
- 単一のカラムに複数の条件をいれる場合
- whereが複数になった場合
- レコード件数のみ取得
- offset(失敗パターン)
- 次ページ取得処理
- 前ページ取得処理(失敗パターン)
- 前ページ取得処理(成功パターン)
- like文
whereとorderbyの関係について
RDBのみたいに簡単にwhereを追加できるのかと思いきや
const colRef = db.collection("members") .where("docId", "!=", "0w9ZviC6D60yR6QVcEjv") .orderBy('createdAt', 'desc') .limit(10); // =>FirebaseError: Invalid query. You have a where filter with an inequality (<, <=, >, or >=) on field 'docId' and so you must also use 'docId' as your first argument to Query.orderBy(), but your first orderBy() is on field 'createdAt' instead
Whereに使用したカラムをorderbyの第1カラムに設定しないといけないもよう・・・
・ω・「まじ使えない」
公式のドキュメントにも記載されています
Cloud Firestore で単純なクエリと複合クエリを実行する | Firebase
whereとorderbyのカラムが違う場合
もしwhereとorderbyが違う場合はsort部分は自前で作る必要があります。
const collectionRef = db.collection("members") var query = await collectionRef.where("docId", "!=", "0w9ZviC6D60yR6QVcEjv").get(); const result = query.docs.map(doc => doc.data()); result.sort(function(a,b){ if(a.createdAt>b.createdAt) return -1; if(a.createdAt < b.createdAt) return 1; return 0; }); console.log(result)
(^o^)「まじ使えない」
データが少ない場合はいいけどデータが多くてページネーションが必要になると
\(^o^)/オワタ
単一のカラムに複数の条件をいれる場合
const collectionRef = db.collection("members") var query = await collectionRef.where("docId", "<=", "0w9ZviC6D60yR6QVcEjv").where("docId", ">=", "0w9ZviC6D60yR6QVcEjv").get(); const result = query.docs.map(doc => doc.data()); console.log(result)
これは問題なく動きました
whereが複数になった場合
単純に「=」のAND処理なら問題なく動きます
const collectionRef = db.collection("members") var query = await collectionRef.where("email", "==", "masalib@gmail.com").where("displayName", "==", "masaddd").get(); const result = query.docs.map(doc => doc.data()); console.log(result)
array-contains 句(<、<=、>、>=、!=)をいれると
const collectionRef = db.collection("members") var query = await collectionRef.where("email", "==", "masalib@gmail.com").where("displayName", ">=", "masaddd").get(); const result = query.docs.map(doc => doc.data()); console.log(result) // FirebaseError: The query requires an index. You can create it here // https://console.firebase.google.com/u/0/project/learn-firebase-masalib/firestore/indexes?create_composite=ClZwcm9qZWN0cy9sZWFybi1maXJlYmFzZS1tYXNhbGliL2RhdGFiYXNlcy8oZGVmYXVsdCkvY29sbGVjdGlvbkdyb3Vwcy9tZW1iZXJzL2luZGV4ZXMvXxABGgkKBWVtYWlsEAEaDwoLZGlzcGxheU5hbWUQARoMCghfX25hbWVfXxAB
複合インデックスを作らないと動かない。 リンクが表示されているのでクリックすると
インデックス作成画面が表示される
Cloud Firestore でのインデックス管理 | Firebase
つくれば動くけど・・・indexは10件ぐらいしかないデータなのに3分もかかりました。
大量のデータならわかるだけどちょっとしたデータならいらんやろ
(^o^)「めんどくさい」
レコード件数のみ取得
2020/12/05の時点ではできない。もし1万件のレコードがある場合は1万件のレコードを取得しないと判別できない。functionsでレコード件数をとれるらしいがまだ検証していない
https://qiita.com/atomyah/items/f94b279febccca030896
(^o^)「え・・ないの??マジで使えない」
offset(失敗パターン)
公式に書いてあったからやってみたが取れなかった
https://googleapis.dev/nodejs/firestore/latest/Query.html#offset
webのモジュールにはないのかな・・・・
const query = await db.collection("members") .orderBy('createdAt', 'desc') .limit(2) .offset(3) .get(); const result = query.docs.map(doc => doc.data()); console.log(result); // => TypeError: _firebase__WEBPACK_IMPORTED_MODULE_2__.db.collection(...).orderBy(...).limit(...).offset is not a function
次ページ取得処理
startAfterというメソッドがある。そちらを使えば簡単にとれる 「XXXXcurrentLastRecordXXXX」は現在、表示しているレコードの最後のレコードになる。 データを取得する度にセットしなければならない。
const query = await db.collection("members") .orderBy('docId', 'desc') .limit(3) .startAfter('XXXXcurrentLastRecordXXXX') .get(); const result = query.docs.map(doc => doc.data()); console.log(result);
前ページ取得処理(失敗パターン)
endAtは後ろからとっていく事をしてくれないので使えなかったwww
const query = await db.collection("members") .orderBy('docId', 'desc') .limit(2) .endAt(XXXXcurrentFirstRecordXXXX) .get(); const result = query.docs.map(doc => doc.data()); console.log(result); //例 // XXXXcurrentFirstRecordXXXXは5とする // 1,2,3,4,5,6,7,8というデータがある // 現在表示しているのは5,6だった場合に // .endAt(5)にすると自分のイメージだと 3,4のデータ取得されると思っていたが // 実際には1,2のデータ取得された。使えない
前ページ取得処理(成功パターン)
const query = await db.collection("members") .orderBy('docId' ) .limit(2) .startAfter(XXXXcurrentFirstRecordXXXX) .get(); console.log(query.size); const result = query.docs.map(doc => doc.data()); //sort処理 result.sort(function(a,b){ if(a.docId>b.docId) return -1; if(a.docId < b.docId) return 1; return 0; }); console.log(result);
.orderBy('docId' )のソートの条件が変わっている事が大事です 自分でソートを逆転してそのデータをローカルにもってきてから更に逆転する事でうまいこと表示できる
例
1,2,3,4,5,6,7,8,9,10,11のデータがある時に、
currentのデータの範囲が4,5,6だった。
XXXXcurrentFirstRecordXXXXは4になる。
4のレコードを基軸にデータを取得する。取得したデータは3,2,1になる。そのデータを逆転ソートをすることで
1,2,3になって正しく表示する事ができる
like文
Likeは標準の機能にないです。以下の記事を参考にしました
const keyword = "masa"; const query = await db.collection("members").orderBy("displayName").startAt(keyword).endAt(keyword + '\uf8ff').get(); const result = query.docs.map(doc => doc.data()); console.log(result);
(^o^)「普通はあるやろ!!」
どうしてこうなった・・・・