एक से ज़्यादा फ़ील्ड पर, रेंज और इनक्वलिटी फ़िल्टर के साथ क्वेरी करने से जुड़ी खास जानकारी

Cloud Firestore, एक ही क्वेरी में कई फ़ील्ड पर रेंज और असमानता वाले फ़िल्टर का इस्तेमाल करता है. एक से ज़्यादा फ़ील्ड के लिए, रेंज और असमानता की शर्तें तय की जा सकती हैं. साथ ही, Cloud Firestore को फ़िल्टर करने के बाद लागू होने वाले लॉजिक को लागू करने का काम सौंपकर, ऐप्लिकेशन डेवलपमेंट को आसान बनाया जा सकता है.

कई फ़ील्ड पर रेंज और असमानता वाले फ़िल्टर

नीचे दी गई क्वेरी में, जनसंख्या और घनत्व पर रेंज फ़िल्टर का इस्तेमाल किया गया है. ऐसा करके, उन सभी शहरों की जानकारी दी गई है जहां जनसंख्या 10,00,000 से ज़्यादा है और जनसंख्या घनत्व 10,000 से कम है.

वेब वर्शन 9 मॉड्यूलर

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)

शुरू करें

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

इंडेक्स करने से जुड़ी बातें

क्वेरी चलाने से पहले, क्वेरी और Cloud Firestore डेटा मॉडल के बारे में पढ़ें.

Cloud Firestore में, क्वेरी के ORDER BY क्लॉज़ से यह तय होता है कि क्वेरी दिखाने के लिए किन इंडेक्स का इस्तेमाल किया जा सकता है. उदाहरण के लिए, ORDER BY a ASC, b ASC क्वेरी के लिए a ASC, b ASC फ़ील्ड पर कंपोज़िट इंडेक्स की ज़रूरत होती है.

Cloud Firestore क्वेरी की परफ़ॉर्मेंस और लागत को ऑप्टिमाइज़ करने के लिए, इंडेक्स में फ़ील्ड के क्रम को ऑप्टिमाइज़ करें. ऐसा करने के लिए, पक्का करें कि आपका इंडेक्स, बाईं से दाईं ओर क्रम में हो, ताकि क्वेरी ऐसे डेटासेट में बदल जाए जो इंडेक्स की ग़ैर-ज़रूरी एंट्री को स्कैन करने से रोकता है.

मान लें कि आपको कर्मचारियों के कलेक्शन में खोज कर, अमेरिका के उन कर्मचारियों को ढूंढना है जिनकी सैलरी 1,00,000 डॉलर से ज़्यादा है और जिनके काम करने के अनुभव के सालों की संख्या 0 से ज़्यादा है. डेटासेट के बारे में अपनी समझ के आधार पर, आपको पता है कि अनुभव की शर्त के मुकाबले, सैलरी की शर्त ज़्यादा चुनिंदा है. इंडेक्स स्कैन की संख्या को कम करने वाला सबसे अच्छा इंडेक्स (salary [...], experience [...]) होगा. इसलिए, तेज़ और कम लागत वाली क्वेरी, salary को experience से पहले ऑर्डर करेगी. यह क्वेरी इस तरह दिखेगी:

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

इंडेक्स को ऑप्टिमाइज़ करने के सबसे सही तरीके

इंडेक्स को ऑप्टिमाइज़ करते समय, इन सबसे सही तरीकों का ध्यान रखें.

इंडेक्स फ़ील्ड को बराबरी के हिसाब से क्रम में लगाएं. इसके बाद, सबसे ज़्यादा चुनी गई रेंज या असमानता वाले फ़ील्ड को क्रम में लगाएं

Cloud Firestore, orderBy() क्वेरी के पहले फ़ील्ड पर, बराबरी की शर्तों और रेंज या असमानता की शर्तों को पूरा करने के लिए, कंपोजिट इंडेक्स के सबसे बाईं ओर मौजूद फ़ील्ड का इस्तेमाल करता है. इन पाबंदियों की वजह से, Cloud Firestore की स्कैन की गई इंडेक्स एंट्री की संख्या कम हो सकती है. Cloud Firestore, इंडेक्स के बाकी फ़ील्ड का इस्तेमाल करके, क्वेरी की अन्य रेंज या असमानता की शर्तों को पूरा करता है. इन पाबंदियों से, Cloud Firestore को स्कैन किए जाने वाले इंडेक्स एंट्री की संख्या कम नहीं होती. हालांकि, मेल न खाने वाले दस्तावेज़ों को फ़िल्टर कर दिया जाता है, ताकि क्लाइंट को दिखाए जाने वाले दस्तावेज़ों की संख्या कम हो जाए.

बेहतर इंडेक्स बनाने के बारे में ज़्यादा जानने के लिए, इंडेक्स प्रॉपर्टी देखें.

क्वेरी की पाबंदी की चुनिंदा वैल्यू के घटते क्रम में फ़ील्ड ऑर्डर करना

यह पक्का करने के लिए कि Cloud Firestore आपकी क्वेरी के लिए सबसे अच्छा इंडेक्स चुनता है, orderBy() क्लॉज़ तय करें. यह क्लॉज़, फ़ील्ड को क्वेरी के लिए चुनी गई पाबंदी के हिसाब से, घटते क्रम में लगाता है. ज़्यादा चुनिंदा शब्दों का इस्तेमाल करने पर, दस्तावेज़ों के छोटे सबसेट से मैच होता है. वहीं, कम चुनिंदा शब्दों का इस्तेमाल करने पर, दस्तावेज़ों के बड़े सबसेट से मैच होता है. पक्का करें कि आपने इंडेक्स ऑर्डर करने के लिए, कम चुनिंदा फ़ील्ड के बजाय, पहले से ही ज़्यादा चुनिंदा रेंज या असमानता वाले फ़ील्ड चुने हों.

Cloud Firestore, नेटवर्क पर स्कैन करके लौटाए जाने वाले दस्तावेज़ों की संख्या कम करने के लिए, फ़ील्ड को हमेशा क्वेरी कंस्ट्रेंट सेलेक्टिविटी के घटते क्रम में क्रम में लगाएं. अगर नतीजा सेट ज़रूरी क्रम में नहीं है और नतीजा सेट छोटा है, तो अपनी पसंद के मुताबिक क्रम में फिर से व्यवस्थित करने के लिए, क्लाइंट-साइड लॉजिक लागू किया जा सकता है.

उदाहरण के लिए, मान लें कि आपको अमेरिका के उन कर्मचारियों को ढूंढना है जिनकी सैलरी 1,00,000 डॉलर से ज़्यादा है. साथ ही, आपको नतीजों को कर्मचारी के अनुभव के हिसाब से क्रम में लगाना है. अगर आपको लगता है कि सिर्फ़ कुछ कर्मचारियों की सैलरी 1,00,000 डॉलर से ज़्यादा होगी, तो क्वेरी लिखने का सबसे सही तरीका यह है:

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`

क्वेरी में experience पर क्रम जोड़ने से, दस्तावेज़ों का वही सेट मिलेगा और क्लाइंट पर नतीजों को फिर से क्रम में लगाने की ज़रूरत नहीं होगी. हालांकि, क्वेरी में पिछली क्वेरी के मुकाबले ज़्यादा इंडेक्स एंट्री पढ़ी जा सकती हैं. इसकी वजह यह है कि Cloud Firestore हमेशा ऐसे इंडेक्स को प्राथमिकता देता है जिसके इंडेक्स फ़ील्ड का प्रीफ़िक्स, क्वेरी के क्लॉज़ के क्रम से मेल खाता हो. अगर experience को क्लॉज़ के मुताबिक ऑर्डर में जोड़ा गया था, तो Cloud Firestore, क्वेरी के नतीजों की गिनती करने के लिए (experience [...], salary [...]) इंडेक्स को चुनेगा. experience पर कोई और पाबंदी नहीं है. इसलिए, आखिरी नतीजों का सेट ढूंढने के लिए salary फ़िल्टर लागू करने से पहले, Cloud Firestore employees कलेक्शन की सभी इंडेक्स एंट्री को पढ़ेगा. इसका मतलब है कि salary फ़िल्टर से मेल न खाने वाली इंडेक्स एंट्री को अब भी पढ़ा जाता है. इससे क्वेरी के इंतज़ार का समय और लागत बढ़ जाती है.

कीमत

एक से ज़्यादा फ़ील्ड पर रेंज और असमानता वाले फ़िल्टर वाली क्वेरी के लिए, पढ़े गए दस्तावेज़ों और इंडेक्स की एंट्री के आधार पर बिलिंग की जाती है.

ज़्यादा जानकारी के लिए, कीमत पेज देखें.

सीमाएं

कई फ़ील्ड पर, रेंज और इनक्वलिटी फ़िल्टर वाली क्वेरी का इस्तेमाल करने से पहले, क्वेरी की सीमाओं के अलावा इन सीमाओं पर ध्यान दें:

  • दस्तावेज़ के फ़ील्ड पर रेंज या इनक्वलिटी फ़िल्टर वाली क्वेरी और दस्तावेज़ कुंजी (__name__) पर, सिर्फ़ 'बराबर है' की पाबंदी वाली क्वेरी का इस्तेमाल नहीं किया जा सकता.
  • Cloud Firestore, रेंज या असमानता वाले फ़ील्ड की संख्या को 10 तक सीमित करता है. ऐसा इसलिए किया जाता है, ताकि क्वेरी को चलाने में बहुत ज़्यादा खर्च न हो.

आगे क्या करना है