Cloud Firestore hỗ trợ sử dụng bộ lọc phạm vi và bất đẳng thức trên nhiều trường trong một truy vấn. Bạn có thể có phạm vi và các điều kiện không bằng nhau trên nhiều trường, đồng thời đơn giản hoá quá trình phát triển ứng dụng bằng cách uỷ quyền triển khai logic sau lọc cho Cloud Firestore.
Bộ lọc phạm vi và bộ lọc bất đẳng thức trên nhiều trường
Truy vấn sau đây sử dụng bộ lọc phạm vi về dân số và mật độ để trả về tất cả các thành phố có dân số trên 1.000.000 người và mật độ dân số dưới 10.000 người trên một đơn vị diện tích.
Phiên bản web 9 mô-đun
const q = query(
collection(db, "cities"),
where('population', '>', 1000000),
where('density', '<', 10000),
);
Swift
let query = db.collection("cities")
.whereField("population", isGreaterThan: 1000000)
.whereField("density", isLessThan: 10000)
Objective-C
FIRQuery *query =
[[[[self.db collectionWithPath:@"cities"]
queryWhereField:@"population" isGreaterThan:@1000000]
queryWhereField:@"density" isLessThan:@10000];
Java Android
Query query = db.collection("cities")
.whereGreaterThan("population", 1000000)
.whereLessThan("density", 10000);
Kotlin+KTX Android
val query = db.collection("cities")
.whereGreaterThan("population", 1000000)
.whereLessThan("density", 10000)
Tiến hành
query := client.Collection("cities").
Where("population", ">", 1000000).
Where("density", "<", 10000)
Java
db.collection("cities")
.whereGreaterThan("population", 1000000)
.whereLessThan("density", 10000);
Node.js
db.collection("cities")
.where('population', '>', 1000000),
.where('density', '<', 10000)
Python
from google.cloud import firestore
db = firestore.Client()
query = db.collection("cities")
.where("population", ">", 1000000)
.where("density", "<", 10000)
PHP
C#
Ruby
query = cities_ref.where("population", ">", "1000000")
.where("density", "<", 10000)
C++
CollectionReference cities_ref = db->Collection("cities");
Query query = cities_ref.WhereGreaterThan("population", FieldValue::Integer(1000000))
.WhereLessThan("density", FieldValue::Integer(10000));
Unity
CollectionReference citiesRef = db.Collection("cities");
Query query = citiesRef.WhereGreaterThan("population", 1000000)
.WhereLessThan("density", 10000);
Dart
final citiesRef = FirebaseFirestore.instance.collection('cities')
final query = citiesRef.where("population", isGreaterThan: 1000000)
.where("density", isLessThan: 10000);
Những điều cần cân nhắc khi lập chỉ mục
Trước khi chạy truy vấn, hãy đọc về truy vấn và mô hình dữ liệu Cloud Firestore.
Trong Cloud Firestore, mệnh đề ORDER BY
của truy vấn xác định những chỉ mục có thể dùng để phân phát truy vấn. Ví dụ: truy vấn ORDER BY a ASC, b ASC
yêu cầu chỉ mục tổng hợp trên các trường a ASC, b ASC
.
Để tối ưu hoá hiệu suất và chi phí của truy vấn Cloud Firestore, hãy tối ưu hoá thứ tự của các trường trong chỉ mục. Để thực hiện việc này, hãy đảm bảo rằng chỉ mục của bạn được sắp xếp từ trái sang phải để truy vấn được tinh lọc thành một tập dữ liệu ngăn việc quét các mục chỉ mục không cần thiết.
Giả sử bạn muốn tìm kiếm trong một tập hợp các nhân viên và tìm những nhân viên ở Hoa Kỳ có mức lương trên 100.000 đô la và số năm kinh nghiệm lớn hơn 0. Dựa trên hiểu biết về tập dữ liệu, bạn biết rằng giới hạn về tiền lương mang tính lựa chọn hơn so với ràng buộc về kinh nghiệm. Chỉ mục lý tưởng giúp giảm số lần quét chỉ mục sẽ là (salary [...], experience [...])
. Do đó, truy vấn nhanh và tiết kiệm chi phí sẽ sắp xếp salary
trước experience
và có dạng như sau:
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");
Các phương pháp hay nhất để tối ưu hoá chỉ mục
Khi tối ưu hoá chỉ mục, hãy lưu ý các phương pháp hay nhất sau đây.
Sắp xếp các trường chỉ mục theo các trường bằng nhau, theo sau là trường phạm vi hoặc bất đẳng thức được chọn nhiều nhất
Cloud Firestore sử dụng các trường ở ngoài cùng bên trái của chỉ mục tổng hợp để đáp ứng các điều kiện ràng buộc bằng nhau và giới hạn phạm vi hoặc bất đẳng thức (nếu có) trên trường đầu tiên của truy vấn orderBy()
. Những quy tắc ràng buộc này có thể làm giảm số lượng mục chỉ mục mà Cloud Firestore quét. Cloud Firestore sử dụng các trường còn lại của chỉ mục để đáp ứng các điều kiện ràng buộc khác về phạm vi hoặc bất đẳng thức của truy vấn. Các điều kiện ràng buộc này không làm giảm số lượng mục nhập chỉ mục mà Cloud Firestore quét, nhưng lọc ra các tài liệu không khớp để giảm số lượng tài liệu được trả về cho ứng dụng.
Để biết thêm thông tin về cách tạo chỉ mục hiệu quả, hãy xem phần thuộc tính chỉ mục.
Sắp xếp các trường theo thứ tự giảm dần về độ chọn lọc của quy tắc ràng buộc truy vấn
Để đảm bảo rằng Cloud Firestore chọn chỉ mục tối ưu cho truy vấn của bạn, hãy chỉ định mệnh đề orderBy()
sắp xếp các trường theo thứ tự giảm dần về độ chọn lọc của điều kiện ràng buộc truy vấn. Độ chọn lọc cao hơn sẽ khớp với một nhóm nhỏ tài liệu, trong khi độ chọn lọc thấp hơn sẽ khớp với một nhóm tài liệu lớn hơn. Đảm bảo rằng bạn chọn các trường phạm vi hoặc bất đẳng thức có độ chọn lọc cao hơn ở đầu thứ tự chỉ mục so với các trường có độ chọn lọc thấp hơn.
Để giảm thiểu số lượng tài liệu mà Cloud Firestore quét và trả về qua mạng, bạn phải luôn sắp xếp các trường theo thứ tự giảm dần về độ chọn lọc của quy tắc ràng buộc truy vấn. Nếu tập hợp kết quả không theo thứ tự bắt buộc và dự kiến sẽ có kích thước nhỏ, bạn có thể triển khai logic phía máy khách để sắp xếp lại tập hợp kết quả theo thứ tự mong muốn.
Ví dụ: giả sử bạn muốn tìm kiếm trong một nhóm nhân viên để tìm những nhân viên Hoa Kỳ có mức lương trên 100.000 USD và sắp xếp kết quả theo năm kinh nghiệm của nhân viên đó. Nếu bạn cho rằng chỉ một số ít nhân viên có mức lương lớn hơn 100.000 USD, thì cách hiệu quả nhất để viết truy vấn như sau:
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`
Mặc dù việc thêm thứ tự trên experience
vào truy vấn sẽ trả về cùng một tập hợp tài liệu và không cần sắp xếp lại kết quả trên ứng dụng, nhưng truy vấn này có thể đọc nhiều mục chỉ mục không liên quan hơn so với truy vấn trước đó. Điều này là do Cloud Firestore luôn ưu tiên một chỉ mục có tiền tố các trường chỉ mục khớp với mệnh đề thứ tự theo của truy vấn. Nếu experience
được thêm vào mệnh đề thứ tự, thì Cloud Firestore sẽ chọn chỉ mục (experience [...], salary [...])
để tính toán kết quả truy vấn. Vì không có quy tắc ràng buộc nào khác trên experience
, nên Cloud Firestore sẽ đọc tất cả mục nhập chỉ mục của tập hợp employees
trước khi áp dụng bộ lọc salary
để tìm tập hợp kết quả cuối cùng. Điều này có nghĩa là các mục chỉ mục không đáp ứng bộ lọc salary
vẫn được đọc, do đó làm tăng độ trễ và chi phí của truy vấn.
Giá
Các truy vấn có bộ lọc phạm vi và bộ lọc bất đẳng thức trên nhiều trường sẽ được tính phí dựa trên số lượng tài liệu đã đọc và số mục nhập chỉ mục đã đọc.
Để biết thông tin chi tiết, hãy xem trang Định giá.
Các điểm hạn chế
Ngoài các giới hạn về truy vấn, hãy lưu ý các giới hạn sau trước khi sử dụng truy vấn có bộ lọc phạm vi và bộ lọc bất đẳng thức trên nhiều trường:
- Không hỗ trợ các truy vấn có bộ lọc phạm vi hoặc bất đẳng thức trên các trường tài liệu và chỉ các quy tắc ràng buộc bằng nhau trên khoá tài liệu
(__name__)
. - Cloud Firestore giới hạn số lượng trường phạm vi hoặc trường bất đẳng thức ở mức 10. Việc này giúp ngăn chặn việc các truy vấn trở nên quá tốn kém để chạy.
Bước tiếp theo
- Tìm hiểu về cách tối ưu hoá truy vấn.
- Tìm hiểu thêm về cách thực hiện các truy vấn đơn giản và truy vấn phức hợp.
- Tìm hiểu cách Cloud Firestore sử dụng chỉ mục.