קוד אינטרנט של Cloud Firestore

1. סקירה כללית

מטרות

בשנת codelab זו, תוכל לבנות יישום אינטרנט המלצה למסעדה מופעל על ידי קלאוד Firestore .

img5.png

מה תלמד

  • קרא וכתוב נתונים ל-Cloud Firestore מאפליקציית אינטרנט
  • האזן לשינויים בנתוני Cloud Firestore בזמן אמת
  • השתמש באימות Firebase ובכללי אבטחה כדי לאבטח נתוני Cloud Firestore
  • כתוב שאילתות מורכבות של Cloud Firestore

מה אתה צריך

לפני שתתחיל מעבדת קוד זה, ודא שהתקנת:

2. צור והגדר פרוייקט Firebase

צור פרויקט Firebase

  1. בשנות ה קונסולת Firebase , לחץ הוסף פרויקט, ולאחר מכן תנו שם FriendlyEats פרויקט Firebase.

זכור את מזהה הפרויקט עבור פרויקט Firebase שלך.

  1. לחץ על צור הפרויקט.

האפליקציה שאנחנו הולכים לבנות משתמשת בכמה שירותי Firebase הזמינים באינטרנט:

  • אימות Firebase בקלות לזהות את המשתמשים שלך
  • ענן Firestore להציל נתונים מובנים ב- Cloud ולקבל הודעה מיידית כאשר הנתונים מתעדכן
  • Firebase אירוח לארח ולשרת נכסים סטטיים שלך

עבור מעבדת הקוד הספציפית הזו, כבר הגדרנו את Firebase Hosting. עם זאת, עבור Firebase Auth ו-Cloud Firestore, אנו נדריך אותך דרך התצורה וההפעלה של השירותים באמצעות קונסולת Firebase.

אפשר אישור אנונימי

למרות שאימות אינו המוקד של מעבדת קוד זה, חשוב שתהיה צורה כלשהי של אימות באפליקציה שלנו. נשתמש התחברות אנונימית - כלומר המשתמש ייחתם בשקט מבלי שתבקש ממנו.

תצטרך לאפשר כניסה אנונימי.

  1. בשנות ה Firebase קונסולת, לאתר את הקטע לבנות הניווט השמאלי.
  2. לחץ אימות, ולאחר מכן לחץ על כניסת כרטיסיית שיטה (או לחץ כאן כדי לעבור ישירות לשם).
  3. אפשר הכניסה אנונימי ספק, ולאחר מכן לחץ על שמור.

img7.png

זה יאפשר לאפליקציה להיכנס בשקט למשתמשים שלך כאשר הם ניגשים לאפליקציית האינטרנט. אל תהסס לקרוא את תיעוד האימות אנונימי כדי ללמוד עוד.

הפעל את Cloud Firestore

האפליקציה משתמשת ב-Cloud Firestore כדי לשמור ולקבל מידע ודירוגי מסעדות.

יהיה עליך להפעיל את Cloud Firestore. במקטע בנה של Firebase המסוף, לחץ מסד firestore. לחץ על צור מסד נתונים בחלונית ענן firestore.

הגישה לנתונים ב-Cloud Firestore נשלטת על ידי כללי אבטחה. נדבר יותר על כללים בהמשך מעבדת הקוד הזה, אבל ראשית עלינו להגדיר כמה כללים בסיסיים על הנתונים שלנו כדי להתחיל. ב הכרטיסייה הכללית של קונסולת Firebase להוסיף את הכללים הבאים ולאחר מכן לחץ על פרסם.

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      //
      // WARNING: These rules are insecure! We will replace them with
      // more secure rules later in the codelab
      //
      allow read, write: if request.auth != null;
    }
  }
}

הכללים שלמעלה מגבילים את הגישה לנתונים למשתמשים שנכנסו, מה שמונע ממשתמשים לא מאומתים לקרוא או לכתוב. זה עדיף מאשר לאפשר גישה לציבור, אבל עדיין רחוק מלהיות מאובטח, נשפר את הכללים האלה מאוחר יותר ב-codelab.

3. קבל את הקוד לדוגמה

לשבט את מאגר GitHub משורת הפקודה:

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

הקוד לדוגמה היה צריך משובטים לתוך 📁 friendlyeats-web בספרייה. מעתה והלאה, הקפד להריץ את כל הפקודות שלך מהספרייה הזו:

cd friendlyeats-web

ייבא את אפליקציית המתנע

באמצעות IDE שלך (WebStorm, Atom, סאבליים, קוד של Visual Studio ...) פתוח או לייבא את 📁 friendlyeats-web בספרייה. ספרייה זו מכילה את קוד ההתחלה של מעבדת הקוד שמורכבת מאפליקציית המלצה למסעדות שעדיין לא מתפקדת. אנו נהפוך אותו לפונקציונלי בכל מעבדת הקוד הזה, כך שתצטרך לערוך קוד בספרייה זו בקרוב.

4. התקן את ממשק שורת הפקודה של Firebase

ממשק שורת הפקודה של Firebase (CLI) מאפשר לך לשרת את אפליקציית האינטרנט שלך באופן מקומי ולפרוס את אפליקציית האינטרנט שלך ל-Firebase Hosting.

  1. התקן את ה-CLI על ידי הפעלת הפקודה npm הבאה:
npm -g install firebase-tools
  1. ודא שה-CLI הותקן כהלכה על ידי הפעלת הפקודה הבאה:
firebase --version

ודא שהגרסה של Firebase CLI היא גרסה 7.4.0 ואילך.

  1. אשר את Firebase CLI על ידי הפעלת הפקודה הבאה:
firebase login

הגדרנו את תבנית אפליקציית האינטרנט כדי למשוך את תצורת האפליקציה שלך עבור Firebase Hosting מהספרייה והקבצים המקומיים של האפליקציה שלך. אבל כדי לעשות זאת, עלינו לשייך את האפליקציה שלך לפרויקט Firebase שלך.

  1. ודא ששורת הפקודה שלך ניגשת לספרייה המקומית של האפליקציה שלך.
  2. שייך את האפליקציה שלך לפרויקט Firebase שלך ​​על ידי הפעלת הפקודה הבאה:
firebase use --add
  1. כשתתבקש, בחר מזהה הפרויקט שלך, ואז לתת פרויקט Firebase שלך בדוי.

כינוי שימושי אם יש לך מספר סביבות (הפקה, הבמה וכו'). עם זאת, עבור codelab זה, בוא פשוט להשתמש בכינוי של 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 , אבל נצטרך לעשות את זה ב האפליקציה עצם כדי להדגים כתיבה בסיסית הענן firestore.

מודל נתונים

נתוני Firestore מפוצלים לאוספים, מסמכים, שדות ותתי-אוספים. אנו נאחסן כל מסעדה כמסמך באוסף ברמה העליונה שנקרא restaurants .

img3.png

מאוחר יותר, אנו נאחסן כל הביקורות בתוך subcollection בשם 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 רגיל. אנו עושים זאת על ידי מקבל הראשון הפניה אוסף ענן Firestore restaurants ואז add "ing את הנתונים.

בואו נוסיף מסעדות!

  1. חזור לאפליקציית FriendlyEats שלך בדפדפן ורענן אותה.
  2. לחץ להוסיף נתונים מוק.

אפליקציית תפיק אוטומטית קבוצה אקראית של חפצי מסעדות, ואז להתקשר שלך addRestaurant הפונקציה. עם זאת, תוכלו עדיין לא רואה את הנתונים של יישום האינטרנט שלך בפועל, כי אנחנו עדיין צריכים ליישם אחזור נתונים (בחלק הבא של codelab).

אם תנווט כרטיסיית הענן Firestore במסוף Firebase, אם כי, אתה אמור לראות מסמכים חדשים 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);
};

בקוד לעיל, אנו בונים שאילתא אשר לאחזר עד 50 מסעדות מן בשם אוסף ברמה העליונה restaurants , אשר מסודרות על פי הדירוג הממוצע (כרגע כל אפס). לאחר שהכרזנו שאילתה זו, אנו עוברים אותו 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 יפעילו התקשרות שלה בכל פעם שיש שינוי לתוצאות השאילתה.

  • בפעם הראשונה, את ההתקשרות מופעלת עם סט התוצאה כול שאילתה - כלומר כול restaurants אוסף מענן firestore. לאחר מכן הוא עובר את כל המסמכים הפרט אל 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

לעת עתה, אינך יכול להוסיף דירוגים מכיוון שאנו עדיין צריכים ליישם הוספת דירוגים מאוחר יותר ב-codelab.

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/.../database/firestore/indexes?create_index=...

השגיאות הללו נובעות מכך ש-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 במסמך המסעדה. במקביל, אנו מוסיפים את החדש rating על ratings subcollection.

12. אבטח את הנתונים שלך

בתחילת מעבדת הקוד הזה, קבענו את כללי האבטחה של האפליקציה שלנו כדי לפתוח לחלוטין את מסד הנתונים לכל קריאה או כתיבה. ביישום אמיתי, נרצה לקבוע כללים הרבה יותר עדינים כדי למנוע גישה או שינוי לא רצויים לנתונים.

  1. במקטע בנה של Firebase המסוף, לחץ מסד firestore.
  2. לחץ על הכרטיסייה כללי בחלק ענן Firestore (או לחץ כאן כדי לעבור ישירות לשם).
  3. החלף את המחדל עם הכללים הבאים, ולאחר מכן לחץ על פרסם.

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 CLI כדי לפרוס כללים לפרויקט Firebase שלך. Firestore.rules הקובץ בספריית העבודה שלך כבר מכיל את הכללים מלמעלה. כדי לפרוס כללים אלה ממערכת הקבצים המקומית שלך (במקום להשתמש במסוף Firebase), תפעיל את הפקודה הבאה:

firebase deploy --only firestore:rules

13. מסקנה

במעבדת הקוד הזה, למדת כיצד לבצע קריאה וכתיבה בסיסית ומתקדמת עם Cloud Firestore, כמו גם כיצד לאבטח גישה לנתונים באמצעות כללי אבטחה. אתה יכול למצוא את הפתרון המלא של מאגר quickstarts-JS .

למידע נוסף על Cloud Firestore, בקר במשאבים הבאים: