การใช้ Firebase Firestore ใน Flutter
ในบทความก่อนหน้า เราได้เรียนรู้วิธีการใช้ Firebase Authentication เพื่อจัดการผู้ใช้งานในแอปพลิเคชัน Flutter ของเรา ในบทนี้ เราจะมาเรียนรู้วิธีการใช้ Firebase Firestore ซึ่งเป็น NoSQL cloud database ที่ยืดหยุ่นและปรับขนาดได้ เพื่อจัดเก็บและซิงค์ข้อมูลสำหรับแอปพลิเคชันของคุณ
Firestore เป็นส่วนหนึ่งของ Firebase platform และให้คุณจัดเก็บข้อมูลในรูปแบบเอกสาร (Documents) ที่จัดกลุ่มอยู่ในคอลเล็กชัน (Collections) ทำให้ง่ายต่อการสร้างแอปพลิเคชันที่ขับเคลื่อนด้วยข้อมูลแบบเรียลไทม์
Firestore คืออะไร?
Firebase Firestore คือฐานข้อมูล NoSQL บน Cloud ที่ออกแบบมาเพื่อ:
- ความยืดหยุ่น: จัดเก็บข้อมูลในรูปแบบเอกสารที่มีโครงสร้างที่แตกต่างกันได้
- การปรับขนาด: สามารถรองรับการเติบโตของข้อมูลและผู้ใช้งานได้อย่างราบรื่น
- ข้อมูลแบบเรียลไทม์: รับการอัปเดตข้อมูลได้ทันทีเมื่อมีการเปลี่ยนแปลง
- การสืบค้นที่มีประสิทธิภาพ: ค้นหาข้อมูลได้อย่างรวดเร็วด้วยการสร้าง index
- การทำงานแบบออฟไลน์: เข้าถึงข้อมูลได้แม้ไม่มีการเชื่อมต่ออินเทอร์เน็ต
การตั้งค่า Firebase Firestore ใน Flutter
ก่อนที่เราจะเริ่มใช้งาน Firestore ได้ เราต้องทำการตั้งค่าโปรเจกต์ Firebase ของเราให้เชื่อมต่อกับแอปพลิเคชัน Flutter ของเราก่อน หากคุณยังไม่ได้ตั้งค่า Firebase โปรดกลับไปที่บทความเกี่ยวกับ Firebase Authentication หรือทำตามขั้นตอนต่อไปนี้:
- สร้างโปรเจกต์ Firebase ใน Firebase console (console.firebase.google.com)
- เพิ่มแอปพลิเคชัน Flutter ของคุณลงในโปรเจกต์ Firebase
- ดาวน์โหลดไฟล์
google-services.json(สำหรับ Android) หรือGoogleService-Info.plist(สำหรับ iOS) และวางไว้ในตำแหน่งที่ถูกต้องในโปรเจกต์ Flutter ของคุณ - เพิ่ม dependencies ที่จำเป็นในไฟล์
pubspec.yaml:
dependencies:
firebase_core: ^2.0.0
cloud_firestore: ^4.0.0
หลังจากนั้น ให้ทำการรันคำสั่ง flutter pub get เพื่อดาวน์โหลด dependencies เหล่านี้
การใช้งาน Collections และ Documents
ใน Firestore ข้อมูลจะถูกจัดเก็บในรูปแบบ Collections และ Documents:
- Collection: กลุ่มของ Documents ที่มีชนิดข้อมูลเดียวกัน เช่น "users" หรือ "products"
- Document: หน่วยข้อมูลที่เล็กที่สุดใน Firestore ประกอบด้วย field ต่างๆ ที่มีค่า (value) เช่น ชื่อ, อายุ, อีเมล
ตัวอย่าง: เราสามารถสร้าง Collection ชื่อ "users" และภายใน Collection นี้จะมี Documents แต่ละ Document แทนผู้ใช้งานแต่ละคน โดยมี field เช่น "name", "email", "age"
การเพิ่มข้อมูลลงใน Firestore
เราสามารถใช้เมธอด add() เพื่อเพิ่ม Document ใหม่ลงใน Collection:
import 'package:cloud_firestore/cloud_firestore.dart';
void addUser() async {
FirebaseFirestore firestore = FirebaseFirestore.instance;
CollectionReference users = firestore.collection('users');
try {
await users.add({
'name': 'John Doe',
'email': 'john.doe@example.com',
'age': 30,
});
print('User added successfully!');
} catch (e) {
print('Error adding user: $e');
}
}
หรือเราสามารถใช้เมธอด set() เพื่อสร้าง Document ใหม่โดยระบุ ID เอง:
void setUser() async {
FirebaseFirestore firestore = FirebaseFirestore.instance;
DocumentReference user = firestore.collection('users').doc('john_doe'); // Specify document ID
try {
await user.set({
'name': 'John Doe',
'email': 'john.doe@example.com',
'age': 30,
});
print('User added successfully!');
} catch (e) {
print('Error adding user: $e');
}
}
การอ่านข้อมูลจาก Firestore
เราสามารถใช้เมธอด get() เพื่อดึงข้อมูลจาก Collection หรือ Document:
void getUser() async {
FirebaseFirestore firestore = FirebaseFirestore.instance;
DocumentReference user = firestore.collection('users').doc('john_doe');
try {
DocumentSnapshot snapshot = await user.get();
if (snapshot.exists) {
print('User data: ${snapshot.data()}');
// Access specific fields:
print('Name: ${snapshot.get('name')}');
print('Email: ${snapshot.get('email')}');
print('Age: ${snapshot.get('age')}');
} else {
print('User does not exist');
}
} catch (e) {
print('Error getting user: $e');
}
}
สำหรับการดึงข้อมูลจาก Collection ทั้งหมด เราสามารถใช้:
void getAllUsers() async {
FirebaseFirestore firestore = FirebaseFirestore.instance;
CollectionReference users = firestore.collection('users');
try {
QuerySnapshot querySnapshot = await users.get();
querySnapshot.docs.forEach((doc) {
print('User ID: ${doc.id}, Data: ${doc.data()}');
});
} catch (e) {
print('Error getting users: $e');
}
}
การอัปเดตข้อมูลใน Firestore
เราสามารถใช้เมธอด update() เพื่ออัปเดตข้อมูลใน Document:
void updateUser() async {
FirebaseFirestore firestore = FirebaseFirestore.instance;
DocumentReference user = firestore.collection('users').doc('john_doe');
try {
await user.update({
'age': 31, // Update the age field
});
print('User updated successfully!');
} catch (e) {
print('Error updating user: $e');
}
}
การลบข้อมูลใน Firestore
เราสามารถใช้เมธอด delete() เพื่อลบ Document:
void deleteUser() async {
FirebaseFirestore firestore = FirebaseFirestore.instance;
DocumentReference user = firestore.collection('users').doc('john_doe');
try {
await user.delete();
print('User deleted successfully!');
} catch (e) {
print('Error deleting user: $e');
}
}
การใช้งาน Queries
Firestore ช่วยให้เราสามารถสืบค้นข้อมูลได้อย่างมีประสิทธิภาพโดยใช้ Queries เราสามารถกรองข้อมูลตามเงื่อนไขต่างๆ ได้
ตัวอย่าง: ค้นหาผู้ใช้งานที่มีอายุมากกว่า 25 ปี:
void getUsersByAge() async {
FirebaseFirestore firestore = FirebaseFirestore.instance;
CollectionReference users = firestore.collection('users');
try {
QuerySnapshot querySnapshot = await users
.where('age', isGreaterThan: 25)
.get();
querySnapshot.docs.forEach((doc) {
print('User ID: ${doc.id}, Data: ${doc.data()}');
});
} catch (e) {
print('Error getting users: $e');
}
}
Firestore รองรับการสืบค้นที่หลากหลาย เช่น isEqualTo, isLessThan, isLessThanOrEqualTo, isGreaterThanOrEqualTo, arrayContains, arrayContainsAny, whereIn, whereNotIn
การใช้งาน Realtime Updates
หนึ่งในคุณสมบัติที่ทรงพลังของ Firestore คือการรองรับ Realtime Updates เราสามารถรับการแจ้งเตือนเมื่อข้อมูลมีการเปลี่ยนแปลงใน Collection หรือ Document โดยใช้ snapshots()
import 'package:flutter/material.dart';
class UserList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection('users').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return ListView(
children: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
return ListTile(
title: Text(data['name']),
subtitle: Text(data['email']),
);
}).toList(),
);
},
);
}
}
ในตัวอย่างนี้ เราใช้ StreamBuilder เพื่อรับ Stream ของ QuerySnapshot จาก Collection "users" เมื่อใดก็ตามที่ข้อมูลใน Collection "users" มีการเปลี่ยนแปลง StreamBuilder จะทำการ rebuild Widget และแสดงข้อมูลใหม่
สรุป
ในบทความนี้ เราได้เรียนรู้วิธีการใช้ Firebase Firestore ใน Flutter เพื่อจัดเก็บและซิงค์ข้อมูล เราได้เรียนรู้วิธีการเพิ่ม, อ่าน, อัปเดต, และลบข้อมูล รวมถึงการสืบค้นข้อมูลและการรับ Realtime Updates Firestore เป็นเครื่องมือที่ทรงพลังสำหรับการสร้างแอปพลิเคชันที่ขับเคลื่อนด้วยข้อมูลแบบเรียลไทม์ ในบทความถัดไป เราจะมาเรียนรู้วิธีการใช้ Firebase Storage เพื่อจัดเก็บไฟล์ต่างๆ เช่น รูปภาพและวิดีโอ