Tổng quan về truy vấn có bộ lọc phạm vi và bất đẳng thức trên nhiều trường

Cloud Firestore hỗ trợ 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ể đặt điều kiện phạm vi và điều kiện 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 lọc sau 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 trên dân số và mật độ để trả về tất cả cá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.

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)

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

$collection = $db->collection('samples/php/cities');
$chainedQuery = $collection
    ->where('population', '>', 1000000)
    ->where('density', '<', 10000);

C#

CollectionReference citiesRef = db.Collection("cities");
Query query = citiesRef
    .WhereGreaterThan("Population", 1000000)
    .WhereLessThan("Density", 10000);
QuerySnapshot querySnapshot = await query.GetSnapshotAsync();
foreach (DocumentSnapshot documentSnapshot in querySnapshot)
{
    var name = documentSnapshot.GetValue<string>("Name");
    var population = documentSnapshot.GetValue<int>("Population");
    var density = documentSnapshot.GetValue<int>("Density");
    Console.WriteLine($"City '{name}' returned by query. Population={population}; Density={density}");
}

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);

Lưu ý về việc lập chỉ mục

Trước khi chạy truy vấn, hãy đọc về truy vấnCloud 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 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 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. Để thực hiện việc này, hãy đảm bảo rằng chỉ mục được sắp xếp từ trái sang phải sao cho truy vấn được rút gọn 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 cao hơn 100.000 USD và 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 cao hơ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 các điều kiện bằng nhau, 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 ở ngoài cùng bên trái của một chỉ mục tổng hợp để đáp ứng các ràng buộc về điều kiện bằng nhau và ràng buộc về phạm vi hoặc ràng buộc về bất đẳng thức (nếu có) trên trường đầu tiên của truy vấn orderBy(). Các ràng buộc này có thể 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 ràng buộc khác về phạm vi hoặc ràng buộc về bất đẳng thức của truy vấn. Cá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 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 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 các thuộc tính chỉ mục.

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

Để đả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. Tính chọn lọc cao hơn sẽ khớp với một tập hợp con nhỏ hơn của tài liệu, trong khi tính chọn lọc thấp hơn sẽ khớp với một tập hợp con lớn hơn của 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 quá trình 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 nên luôn 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. 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 theo kỳ vọng sắp xếp của mình.

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 cao hơ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 cao 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 một thứ tự sắp xếp trên experience vào 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 ứng dụng, 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 một chỉ mục có tiền tố trường chỉ mục khớp với mệnh đề sắp xếp theo của truy vấn. Nếu experience được thêm vào mệnh đề sắp xếp theo, 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 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 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ộ lọc bất đẳng thức trên nhiều trường được tính phí dựa trên số lượng tài liệu được đọc và số lượng mục nhập chỉ mục được đọc.

Để biết thông tin chi tiết, hãy xem trang Giá.

Hạn chế

Ngoài các hạn chế về truy vấn, hãy lưu ý những hạn chế sau đây trước khi sử dụng 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:

  • 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ề điều kiện 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. Điều này là để ngăn các truy vấn trở nên quá tốn kém để chạy.

Bước tiếp theo