はじめに
Firebase Realtime Databaseを触っていたけど、Firestoreはどうなんだろう?
と思って触ってみる。
場合によっては置き換えも視野に入れているので触らざるを得ない!
おそらく時々更新すると思います。
とりあえず、Cloud Firestore を使ってみるで準備を終えておきましょう。
記事を読んで感想や指摘等あればコメントでお願いします。
リアクションがあるとちょっとうれしいです!
※今回のコードは https://github.com/project-dev/flutter_firebase_realtime_database_test に追加してあります。
ログの出力メソッド
とりあえず画面とコンソールにログを出したかったので以下のメソッドを作って処理させています。
Loggerは自作のログ出力クラス。
void _addLog(String text){
setState(() {
_logController.text += "$text\n";
});
Logger.info(text);
}
書き込み
まずはデータを書き込まないと始まらない
新しいコレクションを作成してドキュメントを書き込む
collection()メソッドでコレクション名を指定し、addでドキュメントに格納するフィールドを指定します。
ドキュメントのIDは自動で割り当てられて登録されます。
FirebaseFirestore.instance.collection('users2').add({
'name':'aaaaa',
'age':24
});
既存のコレクションへドキュメントIDを指定して追加する
CollectionReferenceクラスのdoc()メソッドの引数にドキュメント名を指定し、set()メソッドでフィールドを指定します。
CollectionReference users = FirebaseFirestore.instance.collection ('users');
await users.doc("user1").set(
{
"name":"名前",
"age":"45"
}
);
add()メソッドとset()メソッドのポイント
ドキュメントに値を設定する方法はadd()メソッドとset()メソッドの2つがあります。
add()メソッドではドキュメントのIDが自動で生成され、フィールドが設定されます。
set()メソッドはドキュメントIDを設定してフィールドを設定します。
更新
更新は、DocumentReferenceメソッドのset()メソッド、要するに書き込みで使用したset()メソッドで可能です。
Future<void> _updateItem() async{
CollectionReference users = FirebaseFirestore.instance.collection ('users');
await users.doc("user1").set(
{
"name":"名前更新",
"age":"100"
}
);
}
読み込み
単一ドキュメントの読み込み
コレクションを名前を指定して CollectionReference オブジェクトを取得します。
その後、CollectionReferenceクラスのdoc()メソッドで取得したドキュメントIDを指定します。
DocumentReferenceオブジェクトが取得できるので、get()メソッドでフィールドを取得します。
Future<void> _getData() async{
// Userコレクションを取得
var data = await FirebaseFirestore.instance.collection('users').doc('user1').get();
var fields = data.data();
_addLog("Name : ${fields?['name']} / Age : ${fields?['age']}");
}
まとめてドキュメントを読み込み
コレクションを名前を指定して CollectionReference オブジェクトを取得します。
CollectionReferenceクラスの get() メソッドで QuerySnapshotオブジェクト を取得します。
QuerySnapshotオブジェクト のdocsをループで回して、docsの要素である QueryDocumentSnapshot オブジェクトからdata()メソッドでフィールドを取得します。
Future<void> _viewData() async{
// Userコレクションを取得
CollectionReference users = FirebaseFirestore.instance.collection ('users');
// スナップショットからクエリを取得
var querySnapshot = await users.get();
// ドキュメントを表示
for (var doc in querySnapshot.docs) {
_addLog("ID : ${doc.id} / DATA : ${doc.data()}");
}
}
データクラスにデータを格納する
データクラスというかModelというか、クラスにフィールドの内容を格納します。
参考にしたサイトの内容と同じですが・・・
データクラス
class PersonModel{
String name;
int age;
PersonModel({required this.name, required this.age});
}
Future<void> _getDataModel() async{
// Userコレクションを取得
var users = await FirebaseFirestore.instance.collection ('users').get();
var persons = users.docs.map((doc) => PersonModel(
name: doc['name'],
age: int.parse(doc['age'].toString())
)).toList();
_addLog("data length${persons.length}");
for (var model in persons) {
_addLog("Name : ${model.name} / Age : ${model.age}");
}
}
削除
QueryDocumentSnapshotクラスの reference変数を使って削除を行います。
oc.reference.delete()
オフラインでのデータの永続性の設定
以下のように設定すれば永続化されます。
FirebaseFirestore.instance.settings = const Settings(persistenceEnabled: true);
条件指定での抽出
whereで条件を指定して抽出ができる。
Future<void> _getAge20Over() async{
// Userコレクションを取得
var collectionRef = FirebaseFirestore.instance.collection('users');
var query = collectionRef.where("age", isGreaterThanOrEqualTo: 20);
var querySnapshot = await query.get();
_addLog("data length ${querySnapshot.docs.length}");
for (var doc in querySnapshot.docs) {
_addLog("ID : ${doc.id} / DATA : ${doc.data()}");
}
}
そのほかにも様々な抽出方法がある。
そして、制限もあるため、Cloud Firestore で単純なクエリと複合クエリを実行する を参考にすべし。
おまけ
軽くトラブったのでおまけのメモ
FirebaseAuth.instance.signInWithCredential(credential)でype 'List' is not a subtype of type 'PigeonUserDetails?' in type castが発生する
公式の対応はダメだった
pubspec.ymlに記載されているFirebase関連のバージョンを変更し、flutter pub getしたら解決した。
(結局原因はよくわからず・・・)