Cloud Firestore वेब कोडलैब (कोड बनाना सीखना)

1. खास जानकारी

लक्ष्य

इस कोडलैब में, आपको Cloud Firestore की मदद से, रेस्टोरेंट के सुझाव देने वाला वेब ऐप्लिकेशन बनाना होगा.

img5.png

आपको क्या सीखने को मिलेगा

  • वेब ऐप्लिकेशन से Cloud Firestore में डेटा पढ़ना और उसमें डेटा डालना
  • Cloud Firestore के डेटा में होने वाले बदलावों को रीयल टाइम में सुनना
  • Cloud Firestore डेटा को सुरक्षित रखने के लिए, Firebase Authentication और सुरक्षा से जुड़े नियमों का इस्तेमाल करना
  • Cloud Firestore की जटिल क्वेरी लिखना

आपको इन चीज़ों की ज़रूरत होगी

इस कोडलैब को शुरू करने से पहले, पक्का करें कि आपने ये इंस्टॉल कर लिए हों:

  • npm, जो आम तौर पर Node.js के साथ आता है - हमारा सुझाव है कि आप Node 16 या इसके बाद के वर्शन का इस्तेमाल करें
  • आपकी पसंद का आईडीई/टेक्स्ट एडिटर, जैसे कि WebStorm, VS Code या Sublime

2. Firebase प्रोजेक्ट बनाना और उसे सेट अप करना

Firebase प्रोजेक्ट बनाना

  1. Firebase कंसोल में, प्रोजेक्ट जोड़ें पर क्लिक करें. इसके बाद, Firebase प्रोजेक्ट को FriendlyEats नाम दें.

अपने Firebase प्रोजेक्ट का प्रोजेक्ट आईडी याद रखें.

  1. प्रोजेक्ट बनाएं पर क्लिक करें.

हम जो ऐप्लिकेशन बनाने जा रहे हैं वह वेब पर उपलब्ध Firebase की कुछ सेवाओं का इस्तेमाल करता है:

  • अपने उपयोगकर्ताओं की आसानी से पहचान करने के लिए, Firebase से पुष्टि करने की सुविधा
  • Cloud Firestore, ताकि क्लाउड पर स्ट्रक्चर्ड डेटा सेव किया जा सके और डेटा अपडेट होने पर तुरंत सूचना मिल सके
  • अपनी स्टैटिक एसेट को होस्ट और दिखाने के लिए, Firebase होस्टिंग

इस खास कोडलैब के लिए, हमने Firebase होस्टिंग को पहले से कॉन्फ़िगर कर लिया है. हालांकि, Firebase Auth और Cloud Firestore के लिए, हम आपको Firebase कंसोल का इस्तेमाल करके, सेवाओं को कॉन्फ़िगर करने और चालू करने का तरीका बताएंगे.

पहचान छिपाकर पुष्टि करने की सुविधा चालू करना

इस कोडलैब में पुष्टि करने की सुविधा पर फ़ोकस नहीं किया गया है. हालांकि, हमारे ऐप्लिकेशन में पुष्टि करने की कोई सुविधा होना ज़रूरी है. हम बिना नाम वाले लॉगिन का इस्तेमाल करेंगे. इसका मतलब है कि उपयोगकर्ता को बिना किसी सूचना के साइन इन कर दिया जाएगा.

आपको बिना नाम वाले लॉगिन की सुविधा चालू करनी होगी.

  1. Firebase कंसोल में, बाईं ओर मौजूद नेविगेशन में बिल्ड सेक्शन ढूंढें.
  2. पुष्टि करें पर क्लिक करें. इसके बाद, साइन इन करने का तरीका टैब पर क्लिक करें. इसके अलावा, सीधे वहां जाने के लिए यहां क्लिक करें.
  3. अनाम साइन-इन प्रोवाइडर को चालू करें. इसके बाद, सेव करें पर क्लिक करें.

img7.png

इससे, वेब ऐप्लिकेशन को ऐक्सेस करने पर, ऐप्लिकेशन आपके उपयोगकर्ताओं को बिना किसी सूचना के साइन इन कर पाएगा. ज़्यादा जानने के लिए, बिना पहचान ज़ाहिर किए पुष्टि करने से जुड़ा दस्तावेज़ पढ़ें.

Cloud Firestore चालू करना

रेस्टोरेंट की जानकारी और रेटिंग सेव करने और पाने के लिए, ऐप्लिकेशन Cloud Firestore का इस्तेमाल करता है.

आपको Cloud Firestore चालू करना होगा. Firebase कंसोल के बिल्ड सेक्शन में, Firestore डेटाबेस पर क्लिक करें. Cloud Firestore पैनल में, डेटाबेस बनाएं पर क्लिक करें.

Cloud Firestore में डेटा का ऐक्सेस, सुरक्षा नियमों से कंट्रोल किया जाता है. हम इस कोडलैब में बाद में नियमों के बारे में ज़्यादा बात करेंगे. हालांकि, शुरू करने के लिए, हमें अपने डेटा पर कुछ बुनियादी नियम सेट करने होंगे. Firebase कंसोल के नियम टैब में, ये नियम जोड़ें. इसके बाद, पब्लिश करें पर क्लिक करें.

rules_version = '2';
service cloud.firestore {

  // Determine if the value of the field "key" is the same
  // before and after the request.
  function unchanged(key) {
    return (key in resource.data)
      && (key in request.resource.data)
      && (resource.data[key] == request.resource.data[key]);
  }

  match /databases/{database}/documents {
    // Restaurants:
    //   - Authenticated user can read
    //   - Authenticated user can create/update (for demo purposes only)
    //   - Updates are allowed if no fields are added and name is unchanged
    //   - Deletes are not allowed (default)
    match /restaurants/{restaurantId} {
      allow read: if request.auth != null;
      allow create: if request.auth != null;
      allow update: if request.auth != null
                    && (request.resource.data.keys() == resource.data.keys())
                    && unchanged("name");

      // Ratings:
      //   - Authenticated user can read
      //   - Authenticated user can create if userId matches
      //   - Deletes and updates are not allowed (default)
      match /ratings/{ratingId} {
        allow read: if request.auth != null;
        allow create: if request.auth != null
                      && request.resource.data.userId == request.auth.uid;
      }
    }
  }
}

हम इन नियमों और उनके काम करने के तरीके के बारे में, कोडलैब में आगे बात करेंगे.

3. सैंपल कोड पाना

कमांड लाइन से GitHub रिपॉज़िटरी को क्लोन करें:

git clone https://github.com/firebase/friendlyeats-web

सैंपल कोड को 📁friendlyeats-web डायरेक्ट्री में क्लोन किया जाना चाहिए. अब से, सभी कमांड इस डायरेक्ट्री से चलाएं:

cd friendlyeats-web/vanilla-js

स्टार्टर ऐप्लिकेशन इंपोर्ट करना

अपने आईडीई (WebStorm, Atom, Sublime, Visual Studio Code वगैरह) का इस्तेमाल करके, 📁friendlyeats-web डायरेक्ट्री खोलें या इंपोर्ट करें. इस डायरेक्ट्री में, कोडलैब का शुरुआती कोड मौजूद है. इसमें रेस्टोरेंट के सुझाव देने वाला ऐसा ऐप्लिकेशन है जो फ़िलहाल काम नहीं कर रहा है. हम इस कोडलैब में इसे काम करने लायक बना देंगे. इसलिए, आपको जल्द ही उस डायरेक्ट्री में मौजूद कोड में बदलाव करना होगा.

4. Firebase का कमांड-लाइन इंटरफ़ेस इंस्टॉल करना

Firebase कमांड-लाइन इंटरफ़ेस (CLI) की मदद से, अपने वेब ऐप्लिकेशन को स्थानीय तौर पर दिखाया जा सकता है. साथ ही, उसे Firebase होस्टिंग पर डिप्लॉय किया जा सकता है.

  1. npm का यह निर्देश चलाकर, सीएलआई इंस्टॉल करें:
npm -g install firebase-tools
  1. यह पुष्टि करने के लिए कि सीएलआई सही तरीके से इंस्टॉल हुआ है या नहीं, यह कमांड चलाएं:
firebase --version

पक्का करें कि Firebase CLI का वर्शन 7.4.0 या उसके बाद का हो.

  1. यहां दिया गया कमांड चलाकर, Firebase CLI को अनुमति दें:
firebase login

हमने वेब ऐप्लिकेशन टेंप्लेट सेट अप किया है, ताकि आपके ऐप्लिकेशन की लोकल डायरेक्ट्री और फ़ाइलों से, Firebase होस्टिंग के लिए आपके ऐप्लिकेशन का कॉन्फ़िगरेशन खींचा जा सके. हालांकि, ऐसा करने के लिए, हमें आपके ऐप्लिकेशन को आपके Firebase प्रोजेक्ट से जोड़ना होगा.

  1. पक्का करें कि आपकी कमांड लाइन, आपके ऐप्लिकेशन की लोकल डायरेक्ट्री को ऐक्सेस कर रही हो.
  2. अपने ऐप्लिकेशन को Firebase प्रोजेक्ट से जोड़ने के लिए, यह कमांड चलाएं:
firebase use --add
  1. जब कहा जाए, तो अपना प्रोजेक्ट आईडी चुनें. इसके बाद, अपने Firebase प्रोजेक्ट को कोई दूसरा नाम दें.

अगर आपके पास एक से ज़्यादा एनवायरमेंट (प्रोडक्शन, स्टेजिंग वगैरह) हैं, तो कोई दूसरा नाम देना फ़ायदेमंद होता है. हालांकि, इस कोडलैब के लिए, सिर्फ़ default के उपनाम का इस्तेमाल करें.

  1. कमांड लाइन में दिए गए बाकी निर्देशों का पालन करें.

5. लोकल सर्वर चलाना

हम अपने ऐप्लिकेशन पर काम शुरू करने के लिए तैयार हैं! आइए, अपने ऐप्लिकेशन को स्थानीय तौर पर चलाते हैं!

  1. Firebase CLI का यह कमांड चलाएं:
firebase emulators:start --only hosting
  1. आपकी कमांड लाइन में यह रिस्पॉन्स दिखना चाहिए:
hosting: Local server: http://localhost:5000

हम अपने ऐप्लिकेशन को स्थानीय तौर पर उपलब्ध कराने के लिए, Firebase होस्टिंग एमुलेटर का इस्तेमाल कर रहे हैं. वेब ऐप्लिकेशन अब http://localhost:5000 पर उपलब्ध होना चाहिए.

  1. अपना ऐप्लिकेशन http://localhost:5000 पर खोलें.

आपको FriendlyEats की वह कॉपी दिखेगी जिसे आपके Firebase प्रोजेक्ट से कनेक्ट किया गया है.

ऐप्लिकेशन आपके Firebase प्रोजेक्ट से अपने-आप कनेक्ट हो गया है और आपके लिए बिना किसी सूचना के, किसी अनजान उपयोगकर्ता के तौर पर साइन इन कर दिया है.

img2.png

6. Cloud Firestore में डेटा डालना

इस सेक्शन में, हम Cloud Firestore में कुछ डेटा डालेंगे, ताकि हम ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) को पॉप्युलेट कर सकें. Firebase कंसोल की मदद से, मैन्युअल तरीके से भी ऐसा किया जा सकता है. हालांकि, हम ऐप्लिकेशन में ही ऐसा करेंगे, ताकि Cloud Firestore में डेटा डालने का बुनियादी तरीका दिखाया जा सके.

डेटा मॉडल

Firestore डेटा को कलेक्शन, दस्तावेज़, फ़ील्ड, और सब-कलेक्शन में बांटा जाता है. हम हर रेस्टोरेंट को restaurants नाम के टॉप-लेवल कलेक्शन में दस्तावेज़ के तौर पर सेव करेंगे.

img3.png

बाद में, हम हर रेस्टोरेंट के तहत ratings नाम के सब-कलेक्शन में हर समीक्षा को सेव कर देंगे.

img4.png

Firestore में रेस्टोरेंट की जानकारी जोड़ना

हमारे ऐप्लिकेशन में मुख्य मॉडल ऑब्जेक्ट, रेस्टोरेंट है. आइए, कुछ कोड लिखते हैं, जो restaurants कलेक्शन में रेस्टोरेंट का दस्तावेज़ जोड़ता है.

  1. डाउनलोड की गई फ़ाइलों में जाकर, scripts/FriendlyEats.Data.js खोलें.
  2. फ़ंक्शन FriendlyEats.prototype.addRestaurant ढूंढें.
  3. पूरे फ़ंक्शन को इस कोड से बदलें.

FriendlyEats.Data.js

FriendlyEats.prototype.addRestaurant = function(data) {
  var collection = firebase.firestore().collection('restaurants');
  return collection.add(data);
};

ऊपर दिया गया कोड, restaurants कलेक्शन में एक नया दस्तावेज़ जोड़ता है. दस्तावेज़ का डेटा, एक साधारण JavaScript ऑब्जेक्ट से मिलता है. हम ऐसा करने के लिए, सबसे पहले Cloud Firestore कलेक्शन का रेफ़रंस restaurants पाते हैं. इसके बाद, डेटा को add करते हैं.

आइए, रेस्टोरेंट जोड़ें!

  1. अपने ब्राउज़र में FriendlyEats ऐप्लिकेशन पर वापस जाएं और उसे रीफ़्रेश करें.
  2. मॉक डेटा जोड़ें पर क्लिक करें.

ऐप्लिकेशन, रेस्टोरेंट ऑब्जेक्ट का एक रैंडम सेट अपने-आप जनरेट करेगा. इसके बाद, आपके addRestaurant फ़ंक्शन को कॉल करेगा. हालांकि, आपको अपने असल वेब ऐप्लिकेशन में अभी तक डेटा नहीं दिखेगा, क्योंकि हमें अब भी डेटा प्राप्त करने की सुविधा लागू करनी है. यह सुविधा, कोडलैब का अगला सेक्शन है.

हालांकि, Firebase कंसोल में Cloud Firestore टैब पर जाने पर, आपको restaurants कलेक्शन में नए दस्तावेज़ दिखने चाहिए!

img6.png

बधाई हो, आपने अभी-अभी वेब ऐप्लिकेशन से Cloud Firestore में डेटा डाला है!

अगले सेक्शन में, आपको Cloud Firestore से डेटा हासिल करने और उसे अपने ऐप्लिकेशन में दिखाने का तरीका बताया जाएगा.

7. Cloud Firestore से डेटा दिखाना

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

सबसे पहले, रेस्टोरेंट की डिफ़ॉल्ट और बिना फ़िल्टर की गई सूची दिखाने वाली क्वेरी बनाते हैं.

  1. फ़ाइल scripts/FriendlyEats.Data.js पर वापस जाएं.
  2. फ़ंक्शन FriendlyEats.prototype.getAllRestaurants ढूंढें.
  3. पूरे फ़ंक्शन को इस कोड से बदलें.

FriendlyEats.Data.js

FriendlyEats.prototype.getAllRestaurants = function(renderer) {
  var query = firebase.firestore()
      .collection('restaurants')
      .orderBy('avgRating', 'desc')
      .limit(50);

  this.getDocumentsInQuery(query, renderer);
};

ऊपर दिए गए कोड में, हमने एक क्वेरी बनाई है. यह restaurants नाम के टॉप-लेवल कलेक्शन से 50 रेस्टोरेंट तक को वापस लाएगी. ये रेस्टोरेंट, औसत रेटिंग के हिसाब से क्रम में लगाए गए हैं. फ़िलहाल, सभी रेटिंग शून्य हैं. इस क्वेरी को डिक्लेयर्ड करने के बाद, हम इसे getDocumentsInQuery() तरीके पर पास कर देते हैं. यह तरीका, डेटा को लोड और रेंडर करने के लिए ज़िम्मेदार होता है.

हम ऐसा करने के लिए, स्नैपशॉट लिसनर जोड़ेंगे.

  1. फ़ाइल scripts/FriendlyEats.Data.js पर वापस जाएं.
  2. फ़ंक्शन FriendlyEats.prototype.getDocumentsInQuery ढूंढें.
  3. पूरे फ़ंक्शन को इस कोड से बदलें.

FriendlyEats.Data.js

FriendlyEats.prototype.getDocumentsInQuery = function(query, renderer) {
  query.onSnapshot(function(snapshot) {
    if (!snapshot.size) return renderer.empty(); // Display "There are no restaurants".

    snapshot.docChanges().forEach(function(change) {
      if (change.type === 'removed') {
        renderer.remove(change.doc);
      } else {
        renderer.display(change.doc);
      }
    });
  });
};

ऊपर दिए गए कोड में, query.onSnapshot हर बार क्वेरी के नतीजे में बदलाव होने पर, अपना कॉलबैक ट्रिगर करेगा.

  • पहली बार, क्वेरी के पूरे नतीजे सेट के साथ कॉलबैक ट्रिगर होता है – इसका मतलब है कि Cloud Firestore से पूरा restaurants कलेक्शन. इसके बाद, यह सभी दस्तावेज़ों को renderer.display फ़ंक्शन को पास करता है.
  • किसी दस्तावेज़ को मिटाने पर, change.type की वैल्यू removed हो जाती है. इसलिए, इस मामले में हम एक फ़ंक्शन को कॉल करेंगे, जो यूज़र इंटरफ़ेस (यूआई) से रेस्टोरेंट को हटा देगा.

अब हमने दोनों तरीके लागू कर दिए हैं. इसलिए, ऐप्लिकेशन को रीफ़्रेश करें और पुष्टि करें कि Firebase कंसोल में पहले देखे गए रेस्टोरेंट, अब ऐप्लिकेशन में दिख रहे हैं या नहीं. अगर आपने यह सेक्शन पूरा कर लिया है, तो इसका मतलब है कि आपका ऐप्लिकेशन अब Cloud Firestore की मदद से डेटा पढ़ और लिख रहा है!

रेस्टोरेंट की सूची में बदलाव होने पर, यह लिसनर अपने-आप अपडेट होता रहेगा. Firebase कंसोल पर जाकर, मैन्युअल तरीके से किसी रेस्टोरेंट को मिटाएं या उसका नाम बदलें. आपको अपनी साइट पर बदलाव तुरंत दिखेंगे!

img5.png

8. Get() फ़ंक्शन से डेटा पाना

अब तक, हमने रीयल टाइम में अपडेट पाने के लिए, onSnapshot का इस्तेमाल करने का तरीका बताया है. हालांकि, ऐसा हमेशा ज़रूरी नहीं होता. कभी-कभी, डेटा को सिर्फ़ एक बार फ़ेच करना बेहतर होता है.

हम ऐसा तरीका लागू करना चाहते हैं जो तब ट्रिगर हो, जब कोई उपयोगकर्ता आपके ऐप्लिकेशन में किसी खास रेस्टोरेंट पर क्लिक करे.

  1. अपनी फ़ाइल scripts/FriendlyEats.Data.js पर वापस जाएं.
  2. फ़ंक्शन FriendlyEats.prototype.getRestaurant ढूंढें.
  3. पूरे फ़ंक्शन को इस कोड से बदलें.

FriendlyEats.Data.js

FriendlyEats.prototype.getRestaurant = function(id) {
  return firebase.firestore().collection('restaurants').doc(id).get();
};

इस तरीके को लागू करने के बाद, आपको हर रेस्टोरेंट के पेज दिखेंगे. सूची में किसी रेस्टोरेंट पर क्लिक करें. इसके बाद, आपको रेस्टोरेंट की जानकारी वाला पेज दिखेगा:

img1.png

फ़िलहाल, रेटिंग नहीं जोड़ी जा सकतीं, क्योंकि हमें कोडलैब में रेटिंग जोड़ने की सुविधा को बाद में लागू करना है.

9. डेटा को क्रम से लगाना और फ़िल्टर करना

फ़िलहाल, हमारा ऐप्लिकेशन रेस्टोरेंट की सूची दिखाता है. हालांकि, उपयोगकर्ता के पास अपनी ज़रूरतों के हिसाब से फ़िल्टर करने का कोई विकल्प नहीं है. इस सेक्शन में, फ़िल्टर करने की सुविधा चालू करने के लिए, Cloud Firestore की बेहतर क्वेरी का इस्तेमाल किया जाएगा.

सभी Dim Sum रेस्टोरेंट को फ़ेच करने के लिए, यहां एक आसान क्वेरी का उदाहरण दिया गया है:

var filteredQuery = query.where('category', '==', 'Dim Sum')

जैसा कि नाम से पता चलता है, where() तरीके से हमारी क्वेरी, कलेक्शन के सिर्फ़ उन सदस्यों को डाउनलोड करेगी जिनके फ़ील्ड, हमारी सेट की गई पाबंदियों के मुताबिक हों. इस मामले में, सिर्फ़ वे रेस्टोरेंट डाउनलोड किए जाएंगे जिनमें category की वैल्यू Dim Sum है.

हमारे ऐप्लिकेशन में, उपयोगकर्ता कई फ़िल्टर को एक साथ जोड़कर, खास क्वेरी बना सकता है. जैसे, "मुंबई में पिज़्ज़ा" या "लॉस एंजेलिस में लोकप्रियता के हिसाब से समुद्री खाना".

हम एक ऐसा तरीका बनाएंगे जिससे एक क्वेरी बनेगी. यह क्वेरी, हमारे रेस्टोरेंट को उन कई शर्तों के आधार पर फ़िल्टर करेगी जिन्हें हमारे उपयोगकर्ता चुनते हैं.

  1. अपनी फ़ाइल scripts/FriendlyEats.Data.js पर वापस जाएं.
  2. फ़ंक्शन FriendlyEats.prototype.getFilteredRestaurants ढूंढें.
  3. पूरे फ़ंक्शन को इस कोड से बदलें.

FriendlyEats.Data.js

FriendlyEats.prototype.getFilteredRestaurants = function(filters, renderer) {
  var query = firebase.firestore().collection('restaurants');

  if (filters.category !== 'Any') {
    query = query.where('category', '==', filters.category);
  }

  if (filters.city !== 'Any') {
    query = query.where('city', '==', filters.city);
  }

  if (filters.price !== 'Any') {
    query = query.where('price', '==', filters.price.length);
  }

  if (filters.sort === 'Rating') {
    query = query.orderBy('avgRating', 'desc');
  } else if (filters.sort === 'Reviews') {
    query = query.orderBy('numRatings', 'desc');
  }

  this.getDocumentsInQuery(query, renderer);
};

ऊपर दिया गया कोड, उपयोगकर्ता के इनपुट के आधार पर कंपाउंड क्वेरी बनाने के लिए, कई where फ़िल्टर और एक orderBy क्लॉज़ जोड़ता है. हमारी क्वेरी अब सिर्फ़ उन रेस्टोरेंट को दिखाएगी जो उपयोगकर्ता की ज़रूरतों के मुताबिक हों.

अपने ब्राउज़र में FriendlyEats ऐप्लिकेशन को रीफ़्रेश करें. इसके बाद, पुष्टि करें कि कीमत, शहर, और कैटगरी के हिसाब से फ़िल्टर किया जा सकता है. जांच करते समय, आपको अपने ब्राउज़र के JavaScript कंसोल में गड़बड़ियां दिखेंगी. ये गड़बड़ियां इस तरह दिखती हैं:

The query requires an index. You can create it here: https://console.firebase.google.com/project/project-id/database/firestore/indexes?create_composite=...

ये गड़बड़ियां इसलिए होती हैं, क्योंकि Cloud Firestore को ज़्यादातर कंपाउंड क्वेरी के लिए इंडेक्स की ज़रूरत होती है. क्वेरी के लिए इंडेक्स की ज़रूरत होने पर, Cloud Firestore तेज़ी से काम करता रहता है.

गड़बड़ी के मैसेज में दिए गए लिंक को खोलने पर, Firebase कंसोल में इंडेक्स बनाने का यूज़र इंटरफ़ेस (यूआई) अपने-आप खुल जाएगा. इसमें सही पैरामीटर पहले से भरे होंगे. अगले सेक्शन में, हम इस ऐप्लिकेशन के लिए ज़रूरी इंडेक्स लिखेंगे और उन्हें डिप्लॉय करेंगे.

10. इंडेक्स डिप्लॉय करना

अगर हमें अपने ऐप्लिकेशन में हर पाथ को एक्सप्लोर नहीं करना है और इंडेक्स बनाने के हर लिंक पर नहीं जाना है, तो Firebase CLI का इस्तेमाल करके एक साथ कई इंडेक्स आसानी से डिप्लॉय किए जा सकते हैं.

  1. आपके ऐप्लिकेशन की डाउनलोड की गई लोकल डायरेक्ट्री में, आपको एक firestore.indexes.json फ़ाइल मिलेगी.

इस फ़ाइल में, फ़िल्टर के सभी संभावित कॉम्बिनेशन के लिए ज़रूरी सभी इंडेक्स के बारे में बताया गया है.

firestore.indexes.json

{
 "indexes": [
   {
     "collectionGroup": "restaurants",
     "queryScope": "COLLECTION",
     "fields": [
       { "fieldPath": "city", "order": "ASCENDING" },
       { "fieldPath": "avgRating", "order": "DESCENDING" }
     ]
   },

   ...

 ]
}
  1. इन इंडेक्स को इस कमांड की मदद से डिप्लॉय करें:
firebase deploy --only firestore:indexes

कुछ ही मिनटों में, आपके इंडेक्स लाइव हो जाएंगे और गड़बड़ी के मैसेज हट जाएंगे.

11. लेन-देन में डेटा डालना

इस सेक्शन में, हम उपयोगकर्ताओं को रेस्टोरेंट की समीक्षाएं सबमिट करने की सुविधा जोड़ेंगे. अब तक, हमारे सभी डेटा डालने के तरीके, एक-एक डेटा डालने वाले और काफ़ी आसान रहे हैं. अगर इनमें से किसी भी कार्रवाई में कोई गड़बड़ी होती है, तो हम उपयोगकर्ता को उसे फिर से करने के लिए कहेंगे या हमारा ऐप्लिकेशन अपने-आप उसे फिर से करने की कोशिश करेगा.

हमारे ऐप्लिकेशन में ऐसे कई उपयोगकर्ता होंगे जो किसी रेस्टोरेंट को रेटिंग देना चाहेंगे. इसलिए, हमें कई बार डेटा पढ़ने और लिखने की ज़रूरत होगी. सबसे पहले समीक्षा सबमिट करनी होगी. इसके बाद, रेस्टोरेंट की रेटिंग count और average rating को अपडेट करना होगा. अगर इनमें से कोई एक काम नहीं करता है, तो डेटाबेस के एक हिस्से का डेटा दूसरे हिस्से के डेटा से मेल नहीं खाता.

अच्छी बात यह है कि Cloud Firestore में लेन-देन की सुविधा उपलब्ध है. इसकी मदद से, एक ही बार में कई बार डेटा पढ़ा और लिखा जा सकता है. इससे यह पक्का होता है कि हमारा डेटा एक जैसा बना रहे.

  1. अपनी फ़ाइल scripts/FriendlyEats.Data.js पर वापस जाएं.
  2. फ़ंक्शन FriendlyEats.prototype.addRating ढूंढें.
  3. पूरे फ़ंक्शन को इस कोड से बदलें.

FriendlyEats.Data.js

FriendlyEats.prototype.addRating = function(restaurantID, rating) {
  var collection = firebase.firestore().collection('restaurants');
  var document = collection.doc(restaurantID);
  var newRatingDocument = document.collection('ratings').doc();

  return firebase.firestore().runTransaction(function(transaction) {
    return transaction.get(document).then(function(doc) {
      var data = doc.data();

      var newAverage =
          (data.numRatings * data.avgRating + rating.rating) /
          (data.numRatings + 1);

      transaction.update(document, {
        numRatings: data.numRatings + 1,
        avgRating: newAverage
      });
      return transaction.set(newRatingDocument, rating);
    });
  });
};

ऊपर दिए गए ब्लॉक में, हम रेस्टोरेंट के दस्तावेज़ में avgRating और numRatings की अंकों वाली वैल्यू अपडेट करने के लिए, एक लेन-देन ट्रिगर करते हैं. साथ ही, हम ratings सब-कलेक्शन में नया rating जोड़ते हैं.

12. अपना डेटा सुरक्षित करना

इस कोडलैब की शुरुआत में, हमने अपने ऐप्लिकेशन के ऐक्सेस पर पाबंदी लगाने के लिए, ऐप्लिकेशन के सुरक्षा नियम सेट किए थे.

firestore.rules

rules_version = '2';
service cloud.firestore {

  // Determine if the value of the field "key" is the same
  // before and after the request.
  function unchanged(key) {
    return (key in resource.data)
      && (key in request.resource.data)
      && (resource.data[key] == request.resource.data[key]);
  }

  match /databases/{database}/documents {
    // Restaurants:
    //   - Authenticated user can read
    //   - Authenticated user can create/update (for demo purposes only)
    //   - Updates are allowed if no fields are added and name is unchanged
    //   - Deletes are not allowed (default)
    match /restaurants/{restaurantId} {
      allow read: if request.auth != null;
      allow create: if request.auth != null;
      allow update: if request.auth != null
                    && (request.resource.data.keys() == resource.data.keys())
                    && unchanged("name");

      // Ratings:
      //   - Authenticated user can read
      //   - Authenticated user can create if userId matches
      //   - Deletes and updates are not allowed (default)
      match /ratings/{ratingId} {
        allow read: if request.auth != null;
        allow create: if request.auth != null
                      && request.resource.data.userId == request.auth.uid;
      }
    }
  }
}

ये नियम, ऐक्सेस पर पाबंदी लगाते हैं, ताकि यह पक्का किया जा सके कि क्लाइंट सिर्फ़ सुरक्षित बदलाव करें. उदाहरण के लिए:

  • रेस्टोरेंट के दस्तावेज़ में किए गए अपडेट से, रेटिंग में ही बदलाव हो सकता है. नाम या ऐसा कोई अन्य डेटा नहीं बदला जा सकता जिसे बदला नहीं जा सकता.
  • रेटिंग सिर्फ़ तब बनाई जा सकती हैं, जब यूज़र आईडी, साइन इन किए हुए उपयोगकर्ता से मेल खाता हो. इससे स्पूफिंग को रोका जा सकता है.

Firebase कंसोल का इस्तेमाल करने के अलावा, Firebase प्रोजेक्ट में नियमों को डिप्लॉय करने के लिए, Firebase CLI का इस्तेमाल किया जा सकता है. आपकी वर्किंग डायरेक्ट्री में मौजूद firestore.rules फ़ाइल में, ऊपर दिए गए नियम पहले से मौजूद होते हैं. Firebase कंसोल का इस्तेमाल करने के बजाय, अपने लोकल फ़ाइल सिस्टम से इन नियमों को डिप्लॉय करने के लिए, आपको यह कमांड चलाना होगा:

firebase deploy --only firestore:rules

13. नतीजा

इस कोडलैब में, आपको Cloud Firestore में डेटा को पढ़ने और उसमें डेटा जोड़ने के बुनियादी और बेहतर तरीके के बारे में जानकारी मिली. साथ ही, सुरक्षा नियमों की मदद से डेटा को ऐक्सेस करने के तरीके के बारे में भी जानकारी मिली. आपको पूरा समाधान quickstarts-js डेटा स्टोर करने की जगह में मिलेगा.

Cloud Firestore के बारे में ज़्यादा जानने के लिए, इन संसाधनों पर जाएं:

14. [ज़रूरी नहीं] ऐप्लिकेशन की जांच की सुविधा की मदद से लागू करना

Firebase App Check, आपके ऐप्लिकेशन पर अनचाहे ट्रैफ़िक को रोकने और उसकी पुष्टि करने में मदद करके सुरक्षा देता है. इस चरण में, reCAPTCHA Enterprise के साथ App Check जोड़कर, अपनी सेवाओं को ऐक्सेस करने से सुरक्षित किया जा सकता है.

सबसे पहले, आपको ऐप्लिकेशन की जांच करने की सुविधा और reCaptcha को चालू करना होगा.

reCaptcha Enterprise को चालू करना

  1. Cloud Console में, सुरक्षा सेक्शन में जाकर reCaptcha Enterprise ढूंढें और उसे चुनें.
  2. निर्देशों के मुताबिक सेवा चालू करें और की बनाएं पर क्लिक करें.
  3. पूछे जाने पर, कोई डिसप्ले नेम डालें. साथ ही, प्लैटफ़ॉर्म टाइप के तौर पर वेबसाइट चुनें.
  4. डिप्लॉय किए गए यूआरएल को डोमेन सूची में जोड़ें. साथ ही, पक्का करें कि "चेकबॉक्स चैलेंज का इस्तेमाल करें" विकल्प चुना न गया हो.
  5. कुंजी बनाएं पर क्लिक करें और जनरेट की गई कुंजी को सुरक्षित जगह पर सेव करें. आपको इस चरण में बाद में इसकी ज़रूरत पड़ेगी.

ऐप्लिकेशन की जांच करने की सुविधा चालू करना

  1. Firebase कंसोल में, बाएं पैनल में बिल्ड सेक्शन ढूंढें.
  2. ऐप्लिकेशन की जांच करें पर क्लिक करें. इसके बाद, शुरू करें बटन पर क्लिक करें या सीधे कंसोल पर रीडायरेक्ट करें.
  3. रजिस्टर करें पर क्लिक करें. इसके बाद, जब कहा जाए, तब अपनी reCaptcha Enterprise कुंजी डालें. इसके बाद, सेव करें पर क्लिक करें.
  4. एपीआई व्यू में, स्टोरेज चुनें और लागू करें पर क्लिक करें. Cloud Firestore के लिए भी ऐसा ही करें.

अब ऐप्लिकेशन की जांच की सुविधा लागू हो जानी चाहिए! अपना ऐप्लिकेशन रीफ़्रेश करें और रेस्टोरेंट बनाने/देखने की कोशिश करें. आपको गड़बड़ी का यह मैसेज दिखेगा:

Uncaught Error in snapshot listener: FirebaseError: [code=permission-denied]: Missing or insufficient permissions.

इसका मतलब है कि App Check, पुष्टि नहीं किए गए अनुरोधों को डिफ़ॉल्ट रूप से ब्लॉक कर रहा है. अब आपके ऐप्लिकेशन में पुष्टि करने की सुविधा जोड़ते हैं.

FriendlyEats.View.js फ़ाइल पर जाएं और initAppCheck फ़ंक्शन को अपडेट करें. साथ ही, ऐप्लिकेशन की जांच शुरू करने के लिए, अपनी ReCaptcha कुंजी जोड़ें.

FriendlyEats.prototype.initAppCheck = function() {
    var appCheck = firebase.appCheck();
    appCheck.activate(
    new firebase.appCheck.ReCaptchaEnterpriseProvider(
      /* reCAPTCHA Enterprise site key */
    ),
    true // Set to true to allow auto-refresh.
  );
};

appCheck इंस्टेंस को आपकी कुंजी के साथ ReCaptchaEnterpriseProvider से शुरू किया जाता है. साथ ही, isTokenAutoRefreshEnabled से आपके ऐप्लिकेशन में टोकन अपने-आप रीफ़्रेश हो जाते हैं.

लोकल टेस्टिंग चालू करने के लिए, FriendlyEats.js फ़ाइल में वह सेक्शन ढूंढें जहां ऐप्लिकेशन को शुरू किया गया है. इसके बाद, FriendlyEats.prototype.initAppCheck फ़ंक्शन में यह लाइन जोड़ें:

if(isLocalhost) {
  self.FIREBASE_APPCHECK_DEBUG_TOKEN = true;
}

इससे आपके स्थानीय वेब ऐप्लिकेशन के कंसोल में, डीबग टोकन लॉग होगा. यह टोकन इस तरह का होगा:

App Check debug token: 8DBDF614-649D-4D22-B0A3-6D489412838B. You will need to add it to your app's App Check settings in the Firebase console for it to work.

अब, Firebase कंसोल में App Check के ऐप्लिकेशन व्यू पर जाएं.

ओवरफ़्लो मेन्यू पर क्लिक करें और डीबग टोकन मैनेज करें चुनें.

इसके बाद, डीबग टोकन जोड़ें पर क्लिक करें और अपने कंसोल से डीबग टोकन चिपकाएं.

बधाई हो! अब आपके ऐप्लिकेशन में, ऐप्लिकेशन की जांच करने की सुविधा काम करनी चाहिए.