はじめに
数回に分けてNuxt.jsプロジェクトでデータの永続化を行う方法を解説しています。これらの記事は上から順番に読んでいくことを想定しています。
- Nuxt.jsプロジェクトでFirestoreを利用したデータの永続化/取り出しの実装方法
- Nuxt.jsプロジェクトでいろいろな条件を指定してFirestoreからデータを取得する
- Nuxt.jsプロジェクトでFirestoreのデータを変更/削除する
- Nuxt.jsプロジェクトでFirebase Storageに画像ファイルをアップロードする
- Nuxt.jsプロジェクトでFirebase Storageにアップロードした画像を変更/削除する
これらの記事で作成したNuxt.jsプロジェクトは以下のGitHubリポジトリーで公開しています。
GitHub - whitia/nuxt-firebase-sample
前回の記事でFirestoreのデータを取得し表示することができました。しかし、前回は全データをまるっと取得しているだけでした。実際にはいろいろな条件を指定してデータを絞り込むことのほうが多いと思います。
今回は、前回作ったNuxt.jsプロジェクトを使って、Firestoreのデータを条件指定して取得する方法について解説します。
比較条件
前回作ったstore/index.js
のfetchUsers
メソッドを以下のように変更します。
...
fetchUsers({ commit }) {
commit('initUsers')
return new Promise((resolve, reject) => {
// 以下の行を変更
usersRef.where('age', '>=', '25').get()
.then(res => {
res.forEach((doc) => {
commit('addUsers', doc.data())
resolve(true)
})
})
.catch(error => {
console.error('An error occurred in fetchUsers(): ', error)
reject(error)
})
})
}
...
年齢が25歳以上のユーザーに条件を絞ってデータを取得するように変更しました。
25歳未満であるジェーンが除外されました。
以下のように一意なフィールドを条件に指定しても結果は配列で返ってきます。人間が一意なフィールドとして扱っていたとしても、Firestoreにはプライマリキーやユニークキーという概念はありません。
usersRef.where('id', '==', payload.id).get()
.then(snapshot => {
snapshot.forEach(doc => {
// 処理
})
})
今度は以下のように変更してみます。
usersRef.where('age', '>=', '25').order('created_at', 'desc').get()
すると、コンソールに以下のエラーが表示されるます。
Uncaught (in promise) FirebaseError: Invalid query.You have a where filter with an inequality (<, <=, >, or >=) on field 'age' and so you must also use 'age' as your first Query.orderBy(), but your first Query.orderBy() is on field 'created_at' instead.
where
でage
を指定しているのでorderBy
でもage
を指定せよ、という内容です。うーん、謎仕様...
今度は以下の条件に変更してみます。
usersRef.where('name.first', '!=', 'Jane').get()
実行すると以下のエラーが表示されます。
Uncaught (in promise) FirebaseError: Invalid value "!=" provided to function Query.where() for its second argument. Acceptable values: <, <=, ==, >=, >, array-contains, in, array-contains-any
なんと比較演算子にNOT EQUALは使えないとのことです。NOT EQUALとしたいならwhere("age", "<", "30")
とwhere("age", ">", 30)
などと指定する必要があります。
しかしこれは数値などの順番があるフィールドでしか使えません。where('name.first', '!=', 'Jane')
のように特定の文字列を除外する方法はないのです。特定の文字列を除外したい場合は、いったん除外対象のデータを含んだデータを取得して、そのデータに対して以下のように除外するしかありません。
docs.some((doc, index) => {
if (doc.name.first === 'Jane') {
docs.splice(index, 1)
return true
}
})
まとめ
いろいろな条件を指定してFirestoreからデータを取得する方法について解説しました。
Firestoreを一般的なデータベースのような感覚で扱うと思わぬ制限事項にはまることになります。この記事で書いてあることはすべてFirebaseのドキュメントに記載されていることですので、まずはそちらに目を通すことをおすすめします。