Android-Firestore進階查詢

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

--

在Firestore進行查詢,只要簡單地使用where方法就好。但若有其他特別的查詢需求,還可透過函式庫的其他方法組合而成。

本篇要介紹的是:將陣列元素或清單當作查詢條件、查詢結果的排序,以及限制查詢結果數量。使用的是Kotlin語言。

一、陣列元素做為查詢條件

這種查詢方式並不是單純找某些欄位的值,而是以陣列欄位中的元素為查詢標的。假設在「學生」這個類別有個屬性叫「courseCompleted」:

class Student(
var stuId: Int = 0,
var name: String = "",
var birthday: String = "",
var gender: String = "",
var department: String = "",
var courseCompleted: MutableList<String> = mutableListOf()
) {
}

這個新屬性代表學生已經修習完成的課程編號,比方說修完英文課,該List就會有英文課的編號。

學生文件的陣列欄位展示

透過本節介紹的查詢方式,便能找出有修過英文課的學生:

db.collection("Students")
.whereArrayContains("courseCompleted", "EN0123")
.get()
(以下省略)

使用「whereArrayContains」方法,傳入陣列欄位的名稱,再指定要查找的目標元素(假設英文課編號是EN0123)。即可查詢到courseCompleted陣列欄位中,有EN0123這個值的學生。

若讀者寫程式時沒有找到這個方法,請在Gradle檔更新所匯入的Firestore函式庫之版本號。筆者撰寫此文時使用的是:

'com.google.firebase:firebase-firestore:17.1.5'

二、查詢結果的排序

針對欄位對查詢結果排序是SQL常見的功能。在Firestore,查詢結果在開發者沒有定義時,是以「文件ID」遞增的順序傳回前端。若要定義排序,其實也並不難:

db.collection("Students")
.order("age", Query.Direction.DESCENDING)
.get()

只要使用「order」方法,傳入排序依據的欄位,以及遞增或遞減的選項就好。上面是依照年齡(age)遞減排序的範例,而遞增則是「ASCENDING」或省略此參數都可以。

如果想排序多個欄位,只要繼續呼叫order方法即可,然而要注意呼叫的順序。例如先按照學生科系遞增排序,才照年齡遞減排序,會是這樣子寫:

db.collection("Students")
.order("department", Query.Direction.ASCENDING)
.order("age", Query.Direction.DESCENDING)
.get()

三、限制查詢結果數量

在SQL中,有個Top語法可以只取回查詢結果的前幾項,例如取得年齡最高的前10位。而Firestore函式庫同樣有提供這樣的功能。

以這個例子,我們能使用「limit」方法來設定要取多少結果:

db.collection("Students")
.order("age", Query.Direction.DESCENDING)
.limit(10)
.get()

這段查詢是在Students集合中,將文件按照年齡遞減排序,再取回前10項結果。而在程式中,這10項結果(List<DocumentSnapshot>)的年齡也一樣是遞減。

四、清單做為查詢條件

最後筆者個人分享一個OR邏輯的應用,以SQL來比喻,有點像「IN」語法。之前工作時寫過Spring Boot後端程式,需查詢MongoDB資料庫。Mongo的框架內建一個「findByIdIn」的方法,只要傳入字串清單(List<String>),便可得到這些指定文件id的資料。

講白話一點,就是提供一筆「名單」,請資料庫找出名單上所列出的文件。如今換成Firestore,若要仿照出這樣的效果,筆者之前研究出這種做法:

val collection: CollectioReference = db.collection("Students")for (id: Int in studentIds) {
collection.whereEqualTo("stuId", id)
}
collection
.get()

準備一個List(studentIds),裡面存有要查詢的學生id。接著依照「OR邏輯」,將每一個清單元素都當成查詢條件,用where方法附加上去,即可進行查詢。此處是假設學生id的型態為Int,如果是String的話,就請讀者自行替換。

--

--

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

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