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

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

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

यहां दी गई क्वेरी में, जनसंख्या और घनत्व पर रेंज फ़िल्टर का इस्तेमाल किया गया है. इससे, उन सभी शहरों की जानकारी मिलती है जहां जनसंख्या 10 लाख से ज़्यादा है और जनसंख्या घनत्व, इलाके की हर यूनिट में 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 इसके लिए, पक्का करें कि आपका इंडेक्स, बाएं से दाएं क्रम में हो. इससे, क्वेरी ऐसे डेटासेट में बदल जाती है जिससे इंडेक्स की गैर-ज़रूरी एंट्री स्कैन नहीं होती हैं.

मान लें कि आपको कर्मचारियों के कलेक्शन में खोज करनी है और अमेरिका के उन कर्मचारियों की जानकारी ढूंढनी है जिनकी सैलरी एक लाख डॉलर से ज़्यादा है और जिनके पास शून्य से ज़्यादा साल का अनुभव है. डेटासेट के बारे में आपकी समझ के आधार पर, आपको पता है कि सैलरी की शर्त, अनुभव की शर्त से ज़्यादा चुनिंदा है. सबसे सही इंडेक्स (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 नेटवर्क पर स्कैन किए जाने और लौटाए जाने वाले दस्तावेज़ों की संख्या को कम करने के लिए, आपको हमेशा क्वेरी की शर्त की चुनिंदाता के घटते क्रम में फ़ील्ड को क्रम में लगाना चाहिए. अगर नतीजों का सेट, ज़रूरी क्रम में नहीं है और नतीजों का सेट छोटा होने की उम्मीद है, तो क्लाइंट-साइड लॉजिक लागू करके, अपनी उम्मीद के मुताबिक नतीजों को फिर से क्रम में लगाया जा सकता है.

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

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 पर कोई अन्य शर्त लागू न होने की वजह से, Cloud Firestore नतीजों का फ़ाइनल सेट ढूंढने के लिए, salary फ़िल्टर लागू करने से पहले, employees कलेक्शन की सभी इंडेक्स एंट्री पढ़ेगा. इसका मतलब है कि इंडेक्स की वे एंट्री भी पढ़ी जाती हैं जो salary फ़िल्टर की शर्त पूरी नहीं करती हैं. इससे, क्वेरी की लेटेन्सी और लागत बढ़ जाती है.

कीमत

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

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

सीमाएं

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

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

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