이미지 출처: Understanding Collection Group Queries in Cloud Firestore
FireStore 은 NoSQL 형식으로 SQL 관계형데이터 베이스 형식(행과 열이 있는 형식)과는 다르다.
FireStore 은 컬렉션과 문서의 반복으로 나타난다.
각 문서에는 키-값 쌍이 나타난다.
FutureBuilder 안에 Query.get 또는 DocumentReference.get methods를 호출
class GetUserName extends StatelessWidget {
final String documentId;
GetUserName(this.documentId);
@override
Widget build(BuildContext context) {
CollectionReference users = FirebaseFirestore.instance.collection('users');
return FutureBuilder<DocumentSnapshot>(
future: users.doc(documentId).get(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.hasData && !snapshot.data!.exists) {
return Text("Document does not exist");
}
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data = snapshot.data!.data() as Map<String, dynamic>;
return Text("Full Name: ${data['full_name']} ${data['last_name']}");
}
return Text("loading");
},
);
}
}
변화를 감지하는 기능이 존재한다.
CollectionReference
& DocumentReference
둘 다 stream 을 리턴하는 snapshots() 메소드를 제공한다.
Stream collectionStream = FirebaseFirestore.instance.collection('users').snapshots();
Stream documentStream = FirebaseFirestore.instance.collection('users').doc('ABC123').snapshots();
그리고 일단 한번 리턴하면, listen() 메소드를 통해 구독할 수 있다.
아래는 streamBuilder 을 통해 stream state 를 다루는 예시이다.
class UserInformation extends StatefulWidget {
@override
_UserInformationState createState() => _UserInformationState();
}
class _UserInformationState extends State<UserInformation> {
final Stream<QuerySnapshot> _usersStream = FirebaseFirestore.instance.collection('users').snapshots();
@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: _usersStream,
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['full_name']),
subtitle: Text(data['company']),
);
}).toList(),
);
},
);
}
}
그리고 listen 할 때 데이터의 change 는 영향을 끼치지 않지만
includeMetadataChanges
를 통해서 변화를 전달 할 수 있다.
FirebaseFirestore.instance
.collection('users')
.snapshots(includeMetadataChanges: true)