Cloud Firestore는 클라우드에 호스팅되는 NoSQL 데이터베이스 (SDK)
asia-northeast3 is Seoul
컬렉션s - 문서s(키-값 쌍) - 하위컬렉션s - 문서s(키-값 쌍) - 하위컬렉션s ...
표기
추가
업데이트
삭제
문서삭제 docRef.delete() ~ 주의할 점은 문서 내의 하위컬렉션은 삭제되지 않는다는 점! 수동삭제 요망 https://firebase.google.com/docs/firestore/manage-data/delete-data#collections 그래서 문서 삭제 돼도 문서 내의 하위 컬렉션은 그대로 접근이 가능하다.
필드삭제
val updates = hashMapOf<String, Any>(
"capital" to **FieldValue.delete()**
)
docRef.update(updates).addOnCompleteListener { }
컬렉션삭제 전체 컬렉션을 삭제하려면 신뢰할 수 있는 서버 환경에서만 삭제
읽기
문서가져오기 (addOnSuccessListener 에서 확인) val source = Source.CACHE docRef**.get(source)**.addOnSuccessListener { document -> document.data ~ source 를 안 넣어도 된다. 오프라인 대비 캐시다.
커스텀 객체 문서(?) 가져오기
docRef.get().addOnSuccessListener { documentSnapshot ->
val city = documentSnapshot.toObject<City>()
}
컬렉션에서 여러 문서 가져오기
db.collection("cities")
.**whereEqualTo**("capital", true)
.**get**()
.**addOnSuccessListener** { documents ->
for (document in documents) {
Log.d(TAG, "${document.id} => ${document.data}")
}
}
.addOnFailureListener { exception ->
Log.w(TAG, "Error getting documents: ", exception)
}
문서에 리스너 달아서 실시간 업데이트 문서 가져오기
val docRef = db.collection("cities").document("SF")
docRef.**addSnapshotListener** { snapshot, e ->
if (e != null) {
Log.w(TAG, "Listen failed.", e)
return@addSnapshotListener
}
if (snapshot != null && snapshot.exists()) {
Log.d(TAG, "Current data: ${snapshot.data}")
} else {
Log.d(TAG, "Current data: null")
}
}
쿼리넣어서 업데이트 쿼리 결과 문서들 가져오기
db.collection("cities")
**.whereEqualTo("state", "CA")**
.**addSnapshotListener** { value, e ->
if (e != null) {
Log.w(TAG, "Listen failed.", e)
return@addSnapshotListener
}
val cities = ArrayList<String>()
for (doc in value!!) {
doc.getString("name")?.let {
cities.add(it)
}
}
Log.d(TAG, "Current cites in CA: $cities")
}
db.collection("cities")
.whereEqualTo("state", "CA")
.**addSnapshotListener** { snapshots, e ->
if (e != null) {
Log.w(TAG, "listen:error", e)
return@addSnapshotListener
}
for (dc in snapshots!!**.documentChanges**) {
when (dc**.type**) {
DocumentChange.Type.ADDED -> Log.d(TAG, "New city: ${dc.document.data}")
DocumentChange.Type.MODIFIED -> Log.d(TAG, "Modified city: ${dc.document.data}")
DocumentChange.Type.REMOVED -> Log.d(TAG, "Removed city: ${dc.document.data}")
}
}
}
컬렉션에 리스너 달아서 업데이트 문서 가져오기 및 제거
val query = db.collection("cities")
val registration = query.**addSnapshotListener** { snapshots, e ->
// ...
}
// ...
// Stop listening to changes
registration.**remove()**
오류가 발생하면 리스너는 이벤트를 더 이상 수신하지 않으므로 리스너를 분리할 필요 X
단순쿼리
쿼리 결과는 기본적으로 위 읽기 섹션의 get, addSnapshotListener 로 읽어올 수 있음
whereEqualTo(키, 값) collectionRef.whereEqualTo(키, 값)
db.collection("cities")
.whereEqualTo("capital", true)
.get()
.addOnSuccessListener { documents ->
for (document in documents) {
Log.d(TAG, "${document.id} => ${document.data}")
}
}
.addOnFailureListener { exception ->
Log.w(TAG, "Error getting documents: ", exception)
}
whereLessThan
whereGreaterThanOrEqualTo
whereNotEqualTo 지정된 필드가 있는 문서만 쿼리와 일치 가능(다른 Not 붙은 함수도 마찬가지) 복합 쿼리에 결합할 수 없음 복합 쿼리에서 범위(<, <=, >, >=)와 같지 않음(!=, not-in) 비교는 모두 동일한 필드에서 필터링되어야 함
whereArrayContains (쿼리당 최대 1번, array-contains와 array-contains-any를 결합할 수 X)
collectionRef.whereIn("country", listOf("USA", "Japan")) (최대 10개 OR 결합) collectionRef.whereIn("regions", listOf(arrayOf("west_coast"), arrayOf("east_coast")))
collectionRef.whereNotIn("country", listOf("USA", "Japan")) (최대 10개 OR 결합) 쿼리당 in, not-in, array-contains-any 절을 최대 하나만 사용할 수 있음. 같은 쿼리에서 이러한 연산자를 결합할 수 X
collectionRef.whereArrayContainsAny("regions", listOf("west_coast", "east_coast")) 필드 하나에서만 범위(<, <=, >, >=)나 같지 않음(!=) 비교를 할 수 있으며 복합 쿼리에서 최대 1개의 array-contains 또는 array-contains-any 절을 포함할 수 있음
등호(==) 또는 in 절에 포함된 필드를 기준으로 쿼리를 정렬할 수 없음
복합쿼리
collectionRef.whereEqualTo("state", "CO").whereEqualTo("name", "Denver")
collectionRef.whereEqualTo("state", "CA").whereLessThan("population", 1000000)
collectionRef.whereGreaterThanOrEqualTo("state", "CA")
.whereLessThanOrEqualTo("state", "IN")
collectionRef.whereEqualTo("state", "CA")
.whereGreaterThan("population", 1000000)
복합 쿼리에서 범위(<, <=, >, >=)와 같지 않음(!=, not-in) 비교는 모두 동일한 필드에서 필터링되어야 함
컬렉션그룹쿼리
상황 예시로는 어떤 컬렉션에 문서들이 있고 각 문서에 각각 같은 id의 하위컬렉션이 있을 때
db.**collectionGroup**("landmarks").whereEqualTo("type", "museum").get()
.addOnSuccessListener { queryDocumentSnapshots ->
// ...
}
컬렉션 그룹 쿼리를 사용하기 전에 컬렉션 그룹 쿼리를 지원하는 색인을 만들어야 함 https://firebase.google.com/docs/firestore/query-data/indexing https://firebase.google.com/docs/firestore/security/rules-query#secure_and_query_documents_based_on_collection_groups
정렬
페이징