Cloud Firestore hỗ trợ việc 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ể đặt điều kiện về phạm vi và bất đẳng thức 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 khi lọc cho Cloud Firestore.
Bộ lọc phạm vi và 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ả thành phố có dân số cao hơn 1.000.000 người và mật độ dân số thấp hơn 10.000 người trên một đơn vị diện tích.
Web phiên bản 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)
Bắt đầu
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 lưu ý khi lập chỉ mục
Trước khi chạy truy vấn, hãy đọc về [truy vấn][1] và Cloud Firestore [mô hình dữ liệu][2].
Trong Cloud Firestore, mệnh đề ORDER BY của một truy vấn xác định chỉ mục nào 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 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 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 hơn 100.000 USD 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 điều kiện ràng buộc về mức lương có tính chọn lọc cao hơn điều kiện 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 đẳng thức, sau đó là trường bất đẳng thức hoặc phạm vi chọn lọc nhất
Cloud Firestore sử dụng các trường ngoài cùng bên trái của chỉ mục kết hợp để đáp ứng các quy tắc ràng buộc về sự bằng nhau và quy tắc ràng buộc về 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 nhập 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 quy tắc ràng buộc khác về phạm vi hoặc bất đẳng thức của truy vấn. Những quy tắc 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 [thuộc tính chỉ mục][4].
Sắp xếp các trường theo thứ tự giảm dần về mức độ 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ột mệnh đề orderBy() sắp xếp các trường theo thứ tự giảm dần của tính chọn lọc ràng buộc truy vấn. Độ chọn lọc cao hơn sẽ khớp với một tập hợp con tài liệu nhỏ hơn, trong khi độ chọn lọc thấp hơn sẽ khớp với một tập hợp con tài liệu lớn hơn. Hãy đả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 ở vị trí sớm hơn trong 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 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ỏ, thì 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 dự kiến chỉ có 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 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 thứ tự trên experience vào truy vấn sẽ mang lại cùng một tập hợp tài liệu và tránh việc sắp xếp lại kết quả trên máy khách, nhưng truy vấn có thể đọc nhiều mục nhập 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 chỉ mục có tiền tố 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ó quy tắc ràng buộc nào khác đối với 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 nhập 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ất đẳng thức trên nhiều trường được tính phí dựa trên số 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 [Giá][5].
Hạn chế
Ngoài [các giới hạn về truy vấn][6], hãy lưu ý các giới hạn sau đây trước khi sử dụng truy vấn có bộ lọc phạm vi và bất đẳng thức trên nhiều trường:
- 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ác quy tắc ràng buộc đẳng thức trên khoá tài liệu
(__name__)không được hỗ trợ. - Cloud Firestore giới hạn số lượng trường phạm vi hoặc bất đẳng thức ở mức 10. Điều này giúp ngăn 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][3].
- 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][8].
- Tìm hiểu cách [Cloud Firestore sử dụng chỉ mục][9].
[1]: /docs/firestore/query-data/get-data [2]: /docs/firestore/data-model [3]: /docs/firestore/query-data/multiple-range-optimize-indexes [4]: /docs/firestore/concepts/index-overview#index_properties [5]: /docs/firestore/pricing [6]: /docs/firestore/query-data/queries#query_limitations [7]: https://en.wikipedia.org/wiki/Disjunctive_normal_form [8]: /docs/firestore/query-data/queries [9]: /docs/firestore/concepts/index-overview [10]: /docs/firestore/query-data/multiple-range-optimize-indexes