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ể có điều kiện phạm vi và điều kiện bất đẳng thức trên nhiều trường và đơn giản hoá việc 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ộ 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ố 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)

Go

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

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ấnmô 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 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ủ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 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 Mỹ 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 điều kiện ràng buộc về mức lương có tính chọn lọc 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 các đẳng thức, theo sau là phạm vi chọn lọc nhất hoặc trường bất đẳng thức

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 về sự bằng nhau và điều kiện ràng buộc về phạm vi hoặc không bằng nhau (nếu có) trên trường đầu tiên của truy vấn orderBy(). Các 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 đ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ẽ so khớp với một tập hợp con nhỏ hơn của tài liệu, trong khi độ chọn lọc thấp hơn sẽ so 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 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 tập hợp nhân viên để tìm những nhân viên ở Hoa Kỳ có mức lương hơn 100.000 đô la 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 đô la, 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ẽ 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ố trường chỉ mục khớp với mệnh đề thứ tự 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 đối với experience, nên Cloud Firestore sẽ đọc tất cả mục nhập 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 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 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ỉ hỗ trợ 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 bất đẳng thức ở mức 10. Điều 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