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

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

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

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

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

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

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

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 स्कैन करता है. हालांकि, इनसे मेल न खाने वाले दस्तावेज़ों को फ़िल्टर किया जाता है, ताकि क्लाइंट को कम दस्तावेज़ दिखाए जाएं.

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

क्वेरी की शर्त के हिसाब से, फ़ील्ड को घटते क्रम में लगाएं

यह पक्का करने के लिए कि 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 को order by क्लॉज़ में जोड़ा गया है, तो Cloud Firestore, क्वेरी के नतीजों की गिनती करने के लिए (experience [...], salary [...]) इंडेक्स को चुनेगा. experience पर कोई अन्य पाबंदी नहीं है. इसलिए, Cloud Firestore, employees कलेक्शन की सभी इंडेक्स एंट्री को पढ़ेगा. इसके बाद, वह salary फ़िल्टर लागू करके, नतीजों का फ़ाइनल सेट दिखाएगा. इसका मतलब है कि इंडेक्स की ऐसी एंट्री जो salary फ़िल्टर को पूरा नहीं करती हैं उन्हें अब भी पढ़ा जाता है. इससे क्वेरी की इंतज़ार का समय और लागत बढ़ जाती है.

कीमत

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

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

सीमाएं

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

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

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

  • [अपनी क्वेरी को ऑप्टिमाइज़ करने][3] के बारे में जानें.
  • [सिंपल और कंपाउंड क्वेरी करने][8] के बारे में ज़्यादा जानें.
  • यह समझना कि [Cloud Firestore, इंडेक्स का इस्तेमाल कैसे करता है][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