Cloud Firestore hỗ trợ việc sử dụng bộ lọc phạm vi và bộ lọc bất đẳng thức trên nhiều trường trong một truy vấn. Bạn có thể có các điều kiện về phạm vi và sự không bình đẳng 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 lọc hậu kỳ 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 độ dân số để trả về tất cả các thành phố có dân số lớn hơn 1.000.000 người và mật độ dân số nhỏ hơn 10.000 người trên một đơn vị diện tích.
Phiên bản web 9 theo 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)
Tìm
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ểm 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à Cloud Firestore mô hình dữ liệu.
Trong Cloud Firestore, mệnh đề ORDER BY
của một truy vấn xác định những chỉ mục có thể được dùng để phân phát truy vấn. Ví dụ: truy vấn ORDER BY a ASC, b ASC
yêu cầu một chỉ mục kết 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 các truy vấn Cloud Firestore, hãy tối ưu hoá thứ tự của các trường trong chỉ mục. Để làm 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 sao cho truy vấn chắt lọc thành một tập dữ liệu ngăn việc quét các mục nhập 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 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à có số năm kinh nghiệm lớn hơn 0. Dựa trên hiểu biết của bạn về tập dữ liệu, bạn biết rằng ràng buộc về mức lương có tính chọn lọc 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ượng lượt 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 đẳng thức, sau đó là trường phạm vi hoặc trường bất đẳng thức có tính chọn lọc cao nhất
Cloud Firestore sử dụng các trường bên trái cùng của một chỉ mục kết hợp để đáp ứng các ràng buộc về tính bình đẳng và ràng buộc về phạm vi hoặc tính không bình đẳng (nếu có) trên trường đầu tiên của truy vấn orderBy()
. Những 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 ràng buộc khác về phạm vi hoặc sự không bình đẳng của truy vấn. Những 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 sẽ 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 các máy khách.
Để biết thêm thông tin về cách tạo chỉ mục hiệu quả, hãy xem thuộc tính chỉ mục.
Sắp xếp các trường theo thứ tự giảm dần của độ chọn lọ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ột mệnh đề orderBy()
sắp xếp các trường theo thứ tự giảm dần của mức độ chọn lọc ràng buộc truy vấn. Độ chọn lọc cao sẽ khớp với một tập hợp nhỏ hơn các tài liệu, trong khi độ chọn lọc thấp sẽ khớp với một tập hợp lớn hơn các tài liệu. Đảm bảo rằng bạn chọn các trường phạm vi hoặc trường bất đẳng thức có tính chọn lọc cao hơn trong việc sắp xếp chỉ mục so với các trường có tính 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 của mức độ chọn lọc ràng buộc truy vấn. Nếu tập kết quả không theo thứ tự bắt buộc và tập kết quả dự kiến sẽ nhỏ, bạn có thể triển khai logic phía máy khách để sắp xếp lại tậ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 tập hợp 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 số năm kinh nghiệm của nhân viên. Nếu bạn chỉ dự kiến một số ít nhân viên có mức lương trên 100.000 USD, thì cách hiệu quả nhất để viết truy vấn là 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 một thứ tự vào experience
cho truy vấn sẽ tạo ra cùng một tập hợp tài liệu và loại bỏ việc sắp xếp lại kết quả trên các máy khách, nhưng truy vấn có thể đọc nhiều mục nhập chỉ mục thừa 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ủa các trường chỉ mục khớp với mệnh đề order by của truy vấn. Nếu experience
được thêm vào mệnh đề order by, 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ó ràng buộc nào khác đối với experience
, Cloud Firestore sẽ đọc tất cả các mục chỉ mục của bộ sưu tập employees
trước khi áp dụng bộ lọc salary
để tìm tập kết quả cuối cùng. Điều này có nghĩa là các mục trong 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ố lượng mục nhập chỉ mục đã đọc.
Để biết thông tin chi tiết, hãy xem trang Giá.
Các điểm hạn chế
Ngoài các giới hạn về truy vấn, hãy lưu ý những 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ộ lọc bất đẳng thức trên các trường tài liệu và chỉ có các ràng buộc về tính bình đẳng 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 là 10. Điều này nhằm ngăn các truy vấn trở nên quá tốn kém khi 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à phức tạp.
- Tìm hiểu cách Cloud Firestore sử dụng chỉ mục.