Firebase是一家實(shí)時(shí)后端數(shù)據(jù)庫(kù)創(chuàng)業(yè)公司,它能幫助開(kāi)發(fā)者很快的寫(xiě)出Web端和移動(dòng)端的應(yīng)用,無(wú)需管理基礎(chǔ)架構(gòu),快速構(gòu)建您的應(yīng)用。自2014年10月Google收購(gòu)Firebase以來(lái),用戶(hù)可以在更方便地使用Firebase的同時(shí),結(jié)合Google的云服務(wù)。
Cloud Firestore 官方文檔
Cloud Firestore 和 Realtime Database進(jìn)行對(duì)比
- Cloud Firestore 是firebase提供的新型數(shù)據(jù)庫(kù),相比于Realtime Database更直觀的展現(xiàn)數(shù)據(jù),更快的查詢(xún),功能列強(qiáng)大
- 都支持離線(xiàn)模式
- 實(shí)時(shí)數(shù)據(jù)庫(kù)和 Cloud Firestore 都是 NoSQL 數(shù)據(jù)庫(kù)。
- 實(shí)時(shí)數(shù)據(jù)庫(kù)將數(shù)據(jù)存儲(chǔ)為一個(gè)大型 JSON 樹(shù),Cloud Firestore 將數(shù)據(jù)存儲(chǔ)為文檔集合。
數(shù)據(jù)模型
- 文檔 - 在 Cloud Firestore中,存儲(chǔ)單元是文檔。文檔是一個(gè)輕量級(jí)記錄,包含映射到值的字段。每個(gè)文檔都用一個(gè)名稱(chēng)進(jìn)行標(biāo)識(shí)
-
集合 - 文檔存在于集合中,而集合只是文檔的容器
您無(wú)需“創(chuàng)建”或“刪除”集合。在集合中創(chuàng)建第一個(gè)文檔之后,集合才會(huì)存在。如果刪除集合中的所有文檔,集合將不再存在。
所以文檔結(jié)構(gòu)可以是coll/doc/subcoll/subdoc 可以一直嵌套
[圖片上傳失敗...(image-c8ba6a-1592561180755)]
向 Cloud Firestore 添加數(shù)據(jù)
- 在集合中設(shè)置文檔的數(shù)據(jù),并明確指定一個(gè)文檔標(biāo)識(shí)符
- 向集合添加新文檔。在這種情況下,Cloud Firestore 會(huì)自動(dòng)生成文檔標(biāo)識(shí)符。
- 在文檔下面添加相應(yīng)的數(shù)據(jù)
舉個(gè)例子,例如先自定義對(duì)象
data class User(val name: String, val age: Int)
往firestore建立的document michat/users/ 目錄下寫(xiě)入具體數(shù)據(jù),此時(shí)指定了文檔id為users
val mDocRef = FirebaseFirestore.getInstance().collection("michat").document("users")
mDocRef.set(User(nameView.text.toString(), ageView.text.toString().toInt()))
.addOnSuccessListener {
Log.d("FirstFragment", "save success......")
Toast.makeText(context, "save success", Toast.LENGTH_LONG).show()
}
.addOnFailureListener {
Log.d("FirstFragment", "save failed......$it")
Toast.makeText(context, "save failed", Toast.LENGTH_LONG).show()
}
如果有時(shí)無(wú)法為文檔指定有意義的 ID,讓 Cloud Firestore 為您自動(dòng)生成 ID 會(huì)比較方便。您可以通過(guò)調(diào)用 add() 來(lái)實(shí)現(xiàn)此目的:
// Add a new document with a generated id.
val data = hashMapOf(
"name" to "Tokyo",
"country" to "Japan"
)
db.collection("cities")
.add(data)
.addOnSuccessListener { documentReference ->
Log.d(TAG, "DocumentSnapshot written with ID: ${documentReference.id}")
}
.addOnFailureListener { e ->
Log.w(TAG, "Error adding document", e)
}
如果是只更新某個(gè)字段,而不是全覆蓋,也是支持的
mDocRef.update("name", "wangbin-update")
遞增數(shù)值
您可以遞增或遞減數(shù)字字段值,如以下示例所示。遞增或遞減操作會(huì)在字段的當(dāng)前值基礎(chǔ)上增加或減少給定數(shù)量。如果該字段不存在或者當(dāng)前字段值不是數(shù)值,則相應(yīng)操作會(huì)將該字段設(shè)置為給定值。這點(diǎn)在動(dòng)態(tài)配置時(shí)非常靈活
mDocRef.update("age", FieldValue.increment(10))
使用 Cloud Firestore 獲取數(shù)據(jù)
- 獲取單個(gè)文檔,如獲取nearby
先定義nearby對(duì)象用來(lái)解析數(shù)據(jù)
class NearBy : Serializable {
var ad: Ad? = null
var alias: String = ""
override fun toString(): String {
return "${ad?.flag}, ${ad?.index}, $alias"
}
}
class Ad : Serializable {
var flag: Boolean = false
var index: String = ""
}
通過(guò)get來(lái)成功獲取firestore上的nearby文檔
val docRef = FirebaseFirestore.getInstance().collection("michat").document("nearby")
fetchBtn.setOnClickListener {
docRef.get().addOnSuccessListener {
if (it.exists()) {
val result = it.toObject(NearBy::class.java)
Log.d("FirstFragment", "fetch success......$result")
desTv.text = "fetch result:$result"
Toast.makeText(context, "fetch success", Toast.LENGTH_LONG).show()
}
}
.addOnFailureListener {
Log.d("FirstFragment", "fetch failed......$it")
Toast.makeText(context, "fetch failed", Toast.LENGTH_LONG).show()
}
}
- 從集合中獲取多個(gè)文檔
您還可以查詢(xún)某個(gè)集合中的文檔,從而使用一個(gè)請(qǐng)求檢索多個(gè)文檔。例如,您可以使用 where() 來(lái)查詢(xún)滿(mǎn)足特定條件的所有文檔,然后使用 get() 檢索結(jié)果:
FirebaseFirestore.getInstance().collection("michat")
.whereEqualTo("alias", "test").get()
.addOnSuccessListener {
Log.d("FirstFragment", "query success result:$it")
it.forEach { queryDocumentSnapshot ->
Log.d("FirstFragment", "query success result:$queryDocumentSnapshot")
}
}
.addOnFailureListener {
Log.d("FirstFragment", "query failed result:$it")
}
就能查出包含文檔nearby的集合
- 支持?jǐn)?shù)據(jù)庫(kù)查詢(xún)排序
- 簡(jiǎn)單查詢(xún)?nèi)缟厦?code>whereEqualTo
- 復(fù)合查詢(xún)
whereEqualTo("state", "CO").whereEqualTo("name", "Denver") - 對(duì)數(shù)據(jù)進(jìn)行排序
citiesRef.whereGreaterThan("population", 100000).orderBy("population").limit(2),只返回人口超過(guò)100000的前兩個(gè)城市
使用 Cloud Firestore 獲取實(shí)時(shí)更新
- 如實(shí)時(shí)監(jiān)聽(tīng)cloud firestore的變化,可以文檔設(shè)置監(jiān)聽(tīng)
val docRef = FirebaseFirestore.getInstance().collection("michat").document("nearby")
// 監(jiān)聽(tīng)某一document的變化
val registration = docRef.addSnapshotListener(object : EventListener<DocumentSnapshot>{
override fun onEvent(documentSnapshot: DocumentSnapshot?, exception: FirebaseFirestoreException?) {
val result = documentSnapshot?.toObject(NearBy::class.java)
Log.d("FirstFragment", "onEvent listener result$result")
desTv.text = "fetch result:$result"
}
})
這樣就可以設(shè)置對(duì)文檔nearby這一層級(jí)的監(jiān)聽(tīng)。對(duì)于實(shí)時(shí)性非常高的場(chǎng)景,就可以使用監(jiān)聽(tīng);通過(guò)documentSnapshot.metadata.isFromCache來(lái)判斷數(shù)據(jù)是來(lái)自本地緩存或者是來(lái)自服務(wù)器
- 分離監(jiān)聽(tīng)器
當(dāng)不再需要監(jiān)聽(tīng)數(shù)據(jù)時(shí),您必須分離監(jiān)聽(tīng)器,以便停止調(diào)用事件回調(diào)函數(shù)。這樣客戶(hù)端可以停止使用帶寬來(lái)接收更新。例如
registration.remove()
離線(xiàn)訪(fǎng)問(wèn)數(shù)據(jù)
- 對(duì)于 Android 版和 iOS 版應(yīng)用,離線(xiàn)持久化默認(rèn)為啟用狀態(tài)。如需停用持久化,請(qǐng)將 PersistenceEnabled 選項(xiàng)設(shè)置為 false
也可以在初始化的時(shí)候停用離線(xiàn)持久化
val settings = FirebaseFirestoreSettings.Builder()
.setPersistenceEnabled(true)
.build()
db.firestoreSettings = settings
- 當(dāng)設(shè)備在線(xiàn)時(shí)會(huì)優(yōu)先從網(wǎng)絡(luò)獲取文檔;如果您在設(shè)備離線(xiàn)時(shí)獲取文檔,Cloud Firestore 會(huì)從緩存中返回?cái)?shù)據(jù)。如果緩存不包含該文檔的數(shù)據(jù),或該文檔不存在,則 get 調(diào)用會(huì)返回一個(gè)錯(cuò)誤。
- 配置緩存大小
啟用持久化后,Cloud Firestore 會(huì)緩存從后端接收的每個(gè)文檔以便離線(xiàn)訪(fǎng)問(wèn)。Cloud Firestore 為緩存大小設(shè)置默認(rèn)閾值。超出默認(rèn)值后,Cloud Firestore 會(huì)定期嘗試清理較舊的未使用文檔。您可以配置不同的緩存大小閾值,也可以完全停用清理過(guò)程:
// The default cache size threshold is 100 MB. Configure "setCacheSizeBytes"
// for a different threshold (minimum 1 MB) or set to "CACHE_SIZE_UNLIMITED"
// to disable clean-up.
val settings = FirebaseFirestoreSettings.Builder()
.setCacheSizeBytes(FirebaseFirestoreSettings.CACHE_SIZE_UNLIMITED)
.build()
db.firestoreSettings = settings
codelab:
https://codelabs.developers.google.com/codelabs/firestore-android/