在第 19 天的 Cloud Firestore β - 11 研究了簡單的查詢概念,今天就來研究比較進階的查詢方法吧!首先看到昨天學到的 Query 提供的數個查詢方法:
where(fieldPath, opStr, value) returns firebase.firestore.Query
orderBy(fieldPath, directionStr) returns firebase.firestore.Query
limit(limit) returns firebase.firestore.Query
startAt(snapshotOrVarArgs) returns firebase.firestore.Query
endAt(snapshotOrVarArgs) returns firebase.firestore.Query
startAfter(snapshotOrVarArgs) returns firebase.firestore.Query
endBefore(snapshotOrVarArgs) returns firebase.firestore.Query
這幾個方法分別是用來:
where()
:透過條件去篩選集合中的文件。orderBy()
:將得到的資料依照指定欄位進行排序。limit()
:最多拿到幾份資料。startAt()
:從指定的 DocumentSnapshot 、或是指定欄位的某個數值後(含)開始獲取資料。endAt()
:從指定的 DocumentSnapshot 、或是指定欄位的某個數值前(含)開始獲取資料。startAfter()
:從指定的 DocumentSnapshot 、或是指定欄位的某個數值後(不含)開始獲取資料。endBefore()
:從指定的 DocumentSnapshot 、或是指定欄位的某個數值前(不含)開始獲取資料。前面三個還好理解,後面四個就有點不太懂了。沒事,就讓我們透過編寫程式碼去一個個暸解吧。
還記得我們在第 15 天裡的 Cloud Firestore β - 7 裡談到各個欄位的資料型別嗎?在介紹各個資料型別時有提到他們的排序方式,也就是所謂的優先大小的概念。而在 where()
的第二個參數,就是運算子 <
、<=
、==
、>
、>=
,在使用有大小於的比較,就是用那篇提到的排序方式去做比較的。但儘管暸解了這個概念,在非數值的條件篩選,應該還是 ==
的使用情境比較多囉。
let citiesRef = db.collection('cities')
// String `==`
citiesRef.where('state', '==', 'CA')
// Boolean `==`
citiesRef.where('capital', '==', true)
// Number comparison
citiesRef.where('population', '>=', 100000)
// Array
citiesRef.where('districts', 'array-contains', 'west')
至於使用多個 where()
的方式是可以的,這時候都會被當作 AND WHERE
的概念去篩選,在 Cloud Firestore 並沒有 OR WHERE
的概念。但在使用上要注意這兩點:
==
與其他的運算子 <
、<=
、>
、>=
、array-contains
混用時,記得要建立於第 14 天 Cloud Firestore β - 6 所提到的複合索引。<
、<=
、>
、>=
的話,都只能使用在單個欄位上。可以參見以下範例:// Good:兩個範圍篩選的運算子都是用在同一個欄位。
citiesRef.where('state', '>=', 'CA').where('state', '<=', 'IN')
// Good:雖然是用在不同欄位,但是範圍篩選的運算子的確也只用在同一個欄位而已。
citiesRef.where('state', '==', 'CA').where('population', '>', 1000000)
// Bad:用了兩個範圍篩選的運算子,且針對的是不同欄位。
citiesRef.where('state', '>=', 'CA').where('population', '>', 100000)
這邊應該就沒什麼懸念了,第一個參數填寫欄位名稱,第二個參數則填寫排序方式,asc 為升序、desc 為降序。
let citiesQuery = db.collection('cities').order('population', 'desc')
這個我想也很好理解,就是這次拿到的資料筆數。通常會搭配 startAt()
、endAt()
、startAfter()
、endBefore()
去做分頁功能或是分批獲取資料,這部分我們明天來研究。
let topThreePopulationCitiesQuery = db
.collection('cities')
.order('population', 'desc')
.limit(3)