Cloud Firestore 支援在單一查詢中,對多個欄位使用範圍與不等式篩選器。您現在可以在多個欄位上設定範圍和不等式條件,並將篩選後邏輯的實作委派給 Cloud Firestore,以簡化應用程式的開發作業。
多個欄位的範圍和不相等篩選器
以下查詢會傳回年齡大於 35,且高度介於 60 到 70,並使用年齡和高度範圍篩選器的所有使用者。
網頁版 9 模組化
const q = query(
collection(db, "users"),
where('age', '>', 35),
where('height', '>', 60),
where('height', '<', 70)
);
Swift
let query = db.collection("users")
.whereField("age", isGreaterThan: 35)
.whereField("height", isGreaterThan: 60)
.whereField("height", isLessThan: 70)
Objective-C
FIRQuery *query =
[[[[self.db collectionWithPath:@"users"]
queryWhereField:@"age" isGreaterThan:@35]
queryWhereField:@"height" isGreaterThan:@60]
queryWhereField:@"height" isLessThan:@70];
Java Android
Query query = db.collection("users")
.whereGreaterThan("age", 35)
.whereGreaterThan("height", 60)
.whereLessThan("height", 70);
Kotlin+KTX Android
val query = db.collection("users")
.whereGreaterThan("age", 35)
.whereGreaterThan("height", 60)
.whereLessThan("height", 70)
Java
db.collection("users")
.whereGreaterThan("age", 35)
.whereGreaterThan("height", 60)
.whereLessThan("height", 70);
Node.js
db.collection("users")
.where('age', '>', 35),
.where('height', '>', 60),
.where('height', '<', 70)
建立索引註意事項
在開始執行查詢之前,請務必詳閱查詢和 Cloud Firestore 資料模型。
在 Cloud Firestore 中,查詢的 ORDER BY
子句會決定可用於提供查詢的索引。舉例來說,ORDER BY a ASC, b ASC
查詢需要針對 a ASC, b ASC
欄位提供複合式索引。
為提高 Cloud Firestore 查詢的效能與成本效益,請最佳化索引中的欄位順序。若要這麼做,應確保索引的排序方式是從左到右,以使查詢擷取至資料集,以防止掃描極端索引項目。
假設您要搜尋一群員工,並找到薪資超過 10,0000 人且工作年資大於 0 的員工。就您對資料集的瞭解,您知道薪酬限制比體驗限制更廣泛。如要減少索引掃描次數,理想索引會是 (salary [...], experience [...])
。因此,需要快速且符合成本效益的查詢會在 experience
之前排序 salary
,如下所示:
Java
db.collection("employees")
.whereGreaterThan("salary", 100000)
.whereGreaterThan("experience", 0)
.orderBy("salary")
.orderBy("experience");
Node.js
db.collection("employees")
.where("salary", ">", 100000)
.where("experience", ">", 0)
.orderBy("salary")
.orderBy("experience");
Python
db.collection("employees")
.where("salary", ">", 100000)
.where("experience", ">", 0)
.order_by("salary")
.order_by("experience");
最佳化索引的最佳做法
最佳化索引時,請注意下列最佳做法。
排序索引欄位的順序為等號,然後依序為選取範圍或不等式欄位
Cloud Firestore 會使用複合式索引最左側的欄位,在 orderBy()
查詢的第一個欄位中達到等式限制,以及範圍或不等式限制。這些限制可減少 Cloud Firestore 掃描的索引項目數量。Cloud Firestore 會使用索引的其餘欄位來滿足查詢的其他範圍或不等式限制。這些限制不會減少 Cloud Firestore 掃描的索引項目數量,但會篩除不相符的文件,減少傳回給用戶端的文件數量。
如要進一步瞭解如何建立高效率的索引,請參閱完美索引的定義。
按照查詢限制選擇能力遞減排序欄位
為確保 Cloud Firestore 為您的查詢選取最佳索引,請指定 orderBy()
子句,該子句按照查詢限制選擇能力的遞減順序排序欄位。選擇程度越高,應與少數文件子集相符,而選取能力越低,即可與較小型的文件子集相符。請確認在索引排序中,選擇範圍較早的範圍或不等式欄位會比選取程度較低的欄位來得先。
為了盡量減少 Cloud Firestore 透過網路掃描及傳回的文件數量,請務必按照查詢限制選擇能力越低的順序將欄位排序。如果結果集不在必要順序中,且結果集預計會很小,您可以實作用戶端邏輯,依照您的訂購期望重新排序。
舉例來說,假設您想要搜尋一組員工,找出薪資超過 100000 的員工,然後按照員工經驗的年份排序結果。如果您預期只有少數員工的薪資超過 10, 0000 人,那麼編寫查詢的最有效率方法是如下:
Java
db.collection("employees")
.whereGreaterThan("salary", 100000)
.orderBy("salary")
.get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
@Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
// Order results by `experience`
}
});;
Node.js
const querySnapshot = await db.collection('employees')
.where("salary", ">", 100000)
.orderBy("salary")
.get();
// Order results by `experience`
Python
results = db.collection("employees")
.where("salary", ">", 100000)
.order_by("salary")
.stream()
// Order results by `experience`
雖然在 experience
上新增排序後,會產生相同的文件集並難以在用戶端重新排序結果,但查詢可能會讀取比先前的查詢更多多餘的索引項目。這是因為 Cloud Firestore 一律會優先選擇索引欄位前置字串與查詢子句相符的索引。如果按照子句將 experience
加入順序,Cloud Firestore 會選取 (experience [...], salary [...])
索引來計算查詢結果。由於 experience
沒有其他限制,因此 Cloud Firestore 會先讀取 employees
集合的「所有」索引項目,然後再套用 salary
篩選器來尋找最終的結果集。這表示系統仍會讀取不符合 salary
篩選器的索引項目,導致查詢的延遲時間和成本增加。
定價
針對多個欄位套用範圍和不等式篩選器的查詢,將依據讀取的文件和讀取的索引項目計費。
詳情請參閱定價頁面。
限制
除了查詢限制之外,在針對多個欄位使用含有範圍與不等式篩選器的查詢之前,請注意下列限制:
- 查詢不支援在文件欄位上使用範圍或不等式篩選器,且只對文件索引鍵
(__name__)
套用相等限制。 - Cloud Firestore 將範圍或不等式欄位的數量限制為 10。以免查詢費用過高的執行。
後續步驟
- 瞭解如何最佳化查詢。
- 進一步瞭解如何執行簡單和複合查詢。
- 瞭解 Cloud Firestore 如何使用索引。