Android-Firestore更新與刪除資料

Vincent Zheng
新手工程師的程式教室
5 min readJan 7, 2019

更新與刪除資料是資料庫常見的操作。其中Firestore又分成針對整個文件或部份欄位。但與SQL不同的地方在於,這些操作只能對單一文件進行,無法一口氣更新或刪除符合條件的文件。

本文將帶領讀者了解更新資料的各種方式與刪除的操作。使用的是Kotlin語言。

一、更新單一欄位

如果只有一個欄位要更新,可以這樣子寫:

db.collection("Students")
.document("RbHrN4klD...")
.update("age", 23)
.addOnSuccessListener {
Toast.makeText(applicationContext, "更新成功", Toast.LENGTH_SHORT).show()
}

首先就像查詢一樣,利用文件ID取得文件的參照(Document Reference)。接著使用「update」方法,傳入要欄位名稱與新的欄位值,此時便會開始連線,執行修改的動作。

讀者也能在最後加上自己需要的callback程式,等任務完成後,裡面的程式會自動被執行。

二、覆蓋更新

「覆蓋」是指在程式中將新的物件,以文件ID為目標直接取代掉舊的文件。以RESTful API來比喻的話,屬於PUT的概念。

覆蓋文件的程式是這樣子寫的:

db.collection("Students")
.document("RbHrN4klD...")
.set(student)

使用「set」方法,並傳入新的資料作為參數,這樣便能將舊文件整個取代掉。就算新舊文件所具有的欄位成員不同,覆蓋後將一律採用新的。

那麼如果指定的文件ID不存在怎麼辦?此時Firestore會改為建立一個該ID的文件,並將欄位值附加上去。效果等同於用自訂的ID來新增文件。

三、合併更新

在上一節的介紹set方法中,還可以設置有關「merge」的選項。合併(merge)是為了因應前面只能更新整個文件或單一欄位的限制,使開發者能更新多個欄位。

首先介紹完整合併,選項為「SetOptions.merge()」。當使用這個選項,新資料的所有欄位都會附加到舊資料上。而舊資料獨有的欄位則不受影響。

val mapStudent: MutableMap<String, Any> = mutableMapOf(
"stuId" to 10446099,
"name" to "Vincent Zheng",
"emergencyContact" to "Bill Gates")

db.collection("Students")
.document("RbHrN4klD...")
.set(mapStudent, SetOptions.merge())

假設原先的學生文件,有stuId、name、age欄位,而新資料的欄位有stuId、name、emergencyContact。經過完整合併,文件會有四個欄位,且stuId、name的欄位值是來自新資料,而age則維持不變。

接著介紹部份合併,選項有「SetOptions.mergeFields(String… fields)」和「SetOptions.mergeFields(List<String> fields)」兩種。它們需要的參數是字串陣列或List,其中包含了要更新的欄位名稱。

val mapStudent: MutableMap<String, Any> = mutableMapOf(
"stuId" to 10446099,
"name" to "Vincent Zheng",
"age" to 27,
"emergencyContact" to "Bill Gates")

db.collection("Students")
.document("RbHrN4klD...")
.set(mapStudent, SetOptions.mergeFields("stuId", "name"))

延續前例,我們假設新資料已經有原先文件的三個欄位,並且還多了emergencyContact欄位。在使用部份合併時指定了stuId、name欄位名稱,結果會使得文件的這兩個欄位值來自新資料。

至於未指定的age、emergencyContact欄位則被忽略,縱使欄位值是新的,然而是不會合併進來的。

四、刪除資料

刪除整個文件資料非常地簡單,只要取得文件的參照(Document Reference),呼叫方法即可:

db.collection("Students")
.document("RbHrN4klD...")
.delete()
.addOnSuccessListener {
Toast.makeText(applicationContext, "刪除成功", Toast.LENGTH_SHORT).show()
}

讀者可以在最後加上需要的callback程式。除此之外,Firestore也提供刪除單一欄位的方法:

db.collection("Students")
.document("RbHrN4klD...")
.update("department", FieldValue.delete())

只要在更新時,賦予要刪除的單位一個特別的值FieldValue.delete()即可。

刪除欄位完成

--

--

Vincent Zheng
新手工程師的程式教室

我是Vincent,是個來自資管系的後端軟體工程師。當初因為學校作業,才踏出寫部落格的第一步。這裡提供程式教學文章,包含自學和工作上用到的經驗,希望能讓讀者學到東西。我的部落已搬家至 https://chikuwa-tech-study.blogspot.com/