Cloud Firestore Android Codelab

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

מטרות

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

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

דרישות מוקדמות

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

  • Android Studio 4.0 ומעלה
  • אמולטור אנדרואיד עם API 19 ומעלה
  • Node.js גרסה 10 ומעלה
  • Java גרסה 8 ומעלה

2. צור פרויקט Firebase

  1. היכנס למסוף Firebase עם חשבון Google שלך.
  2. במסוף Firebase , לחץ על הוסף פרויקט .
  3. כפי שמוצג בצילום המסך למטה, הזן שם לפרויקט Firebase שלך ​​(לדוגמה, "אוכל ידידותי") ולחץ על המשך .

9d2f625aebcab6af.png

  1. ייתכן שתתבקש להפעיל את Google Analytics, למטרות מעבדת קוד זה הבחירה שלך לא משנה.
  2. לאחר כדקה, פרויקט Firebase שלך ​​יהיה מוכן. לחץ על המשך .

3. הגדר את הפרויקט לדוגמה

הורד את הקוד

הפעל את הפקודה הבאה כדי לשכפל את הקוד לדוגמה עבור מעבדת קוד זה. פעולה זו תיצור תיקייה בשם friendlyeats-android במחשב שלך:

$ git clone https://github.com/firebase/friendlyeats-android

אם אין לך git במחשב שלך, אתה יכול גם להוריד את הקוד ישירות מ-GitHub.

הוסף תצורת Firebase

  1. במסוף Firebase , בחר סקירת פרויקט בניווט השמאלי. לחץ על כפתור אנדרואיד כדי לבחור את הפלטפורמה. כשתתבקש להזין שם חבילה, השתמש ב- com.google.firebase.example.fireeats

73d151ed16016421.png

  1. לחץ על הרשמה אפליקציה ובצע את ההוראות להורדת הקובץ google-services.json , והעבר אותו app/ תיקייה של הקוד שהורדת זה עתה. לאחר מכן לחץ על הבא .

ייבא את הפרויקט

פתח את Android Studio. לחץ על קובץ > חדש > ייבוא ​​פרויקט ובחר בתיקייה friendlyeats-android .

4. הגדר את אמולטורי Firebase

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

התקן את Firebase CLI

ראשית תצטרך להתקין את Firebase CLI . אם אתה משתמש ב-macOS או Linux, אתה יכול להפעיל את הפקודה cURL הבאה:

curl -sL https://firebase.tools | bash

אם אתה משתמש ב-Windows, קרא את הוראות ההתקנה כדי לקבל קובץ בינארי עצמאי או להתקנה באמצעות npm .

לאחר שהתקנת את ה-CLI, הפעלת firebase --version אמורה לדווח על גרסה של 9.0.0 ומעלה:

$ firebase --version
9.0.0

התחברות

הפעל את firebase login כדי לחבר את ה-CLI לחשבון Google שלך. פעולה זו תפתח חלון דפדפן חדש להשלמת תהליך הכניסה. הקפד לבחור באותו חשבון שבו השתמשת בעת יצירת פרויקט Firebase מוקדם יותר.

מתוך התיקיה friendlyeats-android הפעל את firebase use --add כדי לחבר את הפרויקט המקומי שלך לפרויקט Firebase שלך. עקוב אחר ההנחיות כדי לבחור את הפרויקט שיצרת קודם לכן, ואם תתבקש לבחור כינוי הזן default .

5. הפעל את האפליקציה

עכשיו הגיע הזמן להפעיל את Firebase Emulator Suite ואת אפליקציית FriendlyEats Android בפעם הראשונה.

הפעל את האמולטורים

בטרמינל שלך מתוך ספריית friendlyeats-android הפעל firebase emulators:start להפעיל את אמולטורי Firebase. אתה אמור לראות יומנים כמו זה:

$ firebase emulators:start
i  emulators: Starting emulators: auth, firestore
i  firestore: Firestore Emulator logging to firestore-debug.log
i  ui: Emulator UI logging to ui-debug.log

┌─────────────────────────────────────────────────────────────┐
│ ✔  All emulators ready! It is now safe to connect your app. │
│ i  View Emulator UI at http://localhost:4000                │
└─────────────────────────────────────────────────────────────┘

┌────────────────┬────────────────┬─────────────────────────────────┐
│ Emulator       │ Host:Port      │ View in Emulator UI             │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Authentication │ localhost:9099 │ http://localhost:4000/auth      │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Firestore      │ localhost:8080 │ http://localhost:4000/firestore │
└────────────────┴────────────────┴─────────────────────────────────┘
  Emulator Hub running at localhost:4400
  Other reserved ports: 4500

Issues? Report them at https://github.com/firebase/firebase-tools/issues and attach the *-debug.log files.

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

חבר את האפליקציה לאמולטורים

פתח את הקובץ FirebaseUtil.java ב-Android Studio. קובץ זה מכיל את ההיגיון לחיבור ה-SDKs של Firebase לאמולטורים המקומיים הפועלים במחשב שלך.

בחלק העליון של הקובץ, בדוק את השורה הזו:

    /** Use emulators only in debug builds **/
    private static final boolean sUseEmulators = BuildConfig.DEBUG;

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

עכשיו תסתכל על שיטת getFirestore() :

    public static FirebaseFirestore getFirestore() {
        if (FIRESTORE == null) {
            FIRESTORE = FirebaseFirestore.getInstance();

            // Connect to the Cloud Firestore emulator when appropriate. The host '10.0.2.2' is a
            // special IP address to let the Android emulator connect to 'localhost'.
            if (sUseEmulators) {
                FIRESTORE.useEmulator("10.0.2.2", 8080);
            }
        }

        return FIRESTORE;
    }

אנו יכולים לראות שהוא משתמש בשיטת useEmulator(host, port) כדי לחבר את Firebase SDK לאמולטור Firestore המקומי. בכל האפליקציה נשתמש ב- FirebaseUtil.getFirestore() כדי לגשת למופע זה של FirebaseFirestore כך שאנו בטוחים שאנו תמיד מתחברים לאמולטור Firestore כאשר אנו פועלים במצב debug .

הפעל את האפליקציה

אם הוספת את הקובץ google-services.json כהלכה, הפרויקט אמור כעת להדר. ב-Android Studio לחץ על Build > Rebuild Project וודא שלא נותרו שגיאות.

ב-Android Studio הפעל את האפליקציה באמולטור האנדרואיד שלך. בהתחלה יוצג בפניכם מסך "כניסה". אתה יכול להשתמש בכל אימייל וסיסמה כדי להיכנס לאפליקציה. תהליך הכניסה הזה מתחבר לאמולטור Firebase Authentication, כך שלא מועברים אישורים אמיתיים.

כעת פתח את ממשק המשתמש האמולטורים על ידי ניווט אל http://localhost:4000 בדפדפן האינטרנט שלך. לאחר מכן לחץ על הכרטיסייה אימות ואתה אמור לראות את החשבון שיצרת זה עתה:

Firebase Auth Emulator

לאחר השלמת תהליך הכניסה, אתה אמור לראות את מסך הבית של האפליקציה:

de06424023ffb4b9.png

בקרוב נוסיף כמה נתונים כדי לאכלס את מסך הבית.

6. כתוב נתונים ל-Firestore

בחלק זה נכתוב כמה נתונים ל-Firestore כדי שנוכל לאכלס את מסך הבית הריק כרגע.

אובייקט הדגם העיקרי באפליקציה שלנו הוא מסעדה (ראה model/Restaurant.java ). נתוני Firestore מפוצלים למסמכים, אוספים ותתי-אוספים. נאחסן כל מסעדה כמסמך באוסף ברמה העליונה הנקראת "restaurants" . למידע נוסף על מודל הנתונים של Firestore, קרא על מסמכים ואוספים בתיעוד .

למטרות הדגמה, נוסיף פונקציונליות באפליקציה ליצירת עשר מסעדות אקראיות כאשר נלחץ על כפתור "הוסף פריטים אקראיים" בתפריט ההצפה. פתח את הקובץ MainActivity.java והחלף את התוכן בשיטה onAddItemsClicked() ב:

    private void onAddItemsClicked() {
        // Get a reference to the restaurants collection
        CollectionReference restaurants = mFirestore.collection("restaurants");

        for (int i = 0; i < 10; i++) {
            // Get a random Restaurant POJO
            Restaurant restaurant = RestaurantUtil.getRandom(this);

            // Add a new document to the restaurants collection
            restaurants.add(restaurant);
        }
    }

יש כמה דברים שחשוב לשים לב לקוד למעלה:

  • התחלנו בהפניה לאוסף "restaurants" . אוספים נוצרים באופן מרומז כאשר מוסיפים מסמכים, כך שלא היה צורך ליצור את האוסף לפני כתיבת נתונים.
  • ניתן ליצור מסמכים באמצעות POJOs (Plain Old Java Object), שבהם אנו משתמשים ליצירת כל מסמך של מסעדה.
  • השיטה add() מוסיפה מסמך לאוסף עם מזהה שנוצר אוטומטית, כך שלא היינו צריכים לציין מזהה ייחודי לכל מסעדה.

כעת הפעל את האפליקציה שוב ולחץ על כפתור "הוסף פריטים אקראיים" בתפריט ההצפה (בפינה השמאלית העליונה) כדי להפעיל את הקוד שזה עתה כתבת:

95691e9b71ba55e3.png

כעת פתח את ממשק המשתמש האמולטורים על ידי ניווט אל http://localhost:4000 בדפדפן האינטרנט שלך. לאחר מכן לחץ על הכרטיסייה Firestore ואתה אמור לראות את הנתונים שזה עתה הוספת:

Firebase Auth Emulator

נתונים אלה הם 100% מקומיים למחשב שלך. למעשה, הפרויקט האמיתי שלך אפילו לא מכיל מסד נתונים של Firestore עדיין! משמעות הדבר היא שבטוח להתנסות בשינוי ומחיקה של נתונים אלה ללא השלכות.

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

7. הצג נתונים מ-Firestore

בשלב זה נלמד כיצד לאחזר נתונים מ-Firestore ולהציג אותם באפליקציה שלנו. הצעד הראשון לקריאת נתונים מ-Firestore הוא יצירת Query . פתח את הקובץ MainActivity.java והוסף את הקוד הבא לתחילת השיטה onCreate() :

        mFirestore = FirebaseUtil.getFirestore();

        // Get the 50 highest rated restaurants
        mQuery = mFirestore.collection("restaurants")
                .orderBy("avgRating", Query.Direction.DESCENDING)
                .limit(LIMIT);

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

פתח את המחלקה FirestoreAdapter , שכבר יושמה חלקית. ראשית, בואו נגרום למתאם ליישם את EventListener ולהגדיר את הפונקציה onEvent כך שהוא יוכל לקבל עדכונים לשאילתת Firestore:

public abstract class FirestoreAdapter<VH extends RecyclerView.ViewHolder>
        extends RecyclerView.Adapter<VH>
        implements EventListener<QuerySnapshot> { // Add this "implements"

    // ...

    // Add this method
    @Override
    public void onEvent(QuerySnapshot documentSnapshots,
                        FirebaseFirestoreException e) {

        // Handle errors
        if (e != null) {
            Log.w(TAG, "onEvent:error", e);
            return;
        }

        // Dispatch the event
        for (DocumentChange change : documentSnapshots.getDocumentChanges()) {
            // Snapshot of the changed document
            DocumentSnapshot snapshot = change.getDocument();

            switch (change.getType()) {
                case ADDED:
                    // TODO: handle document added
                    break;
                case MODIFIED:
                    // TODO: handle document modified
                    break;
                case REMOVED:
                    // TODO: handle document removed
                    break;
            }
        }

        onDataChanged();
    }

  // ...
}

בטעינה ראשונית המאזין יקבל אירוע ADDED אחד עבור כל מסמך חדש. כאשר מערך התוצאות של השאילתה משתנה לאורך זמן המאזין יקבל יותר אירועים המכילים את השינויים. כעת נסיים ליישם את המאזין. תחילה הוסף שלוש שיטות חדשות: onDocumentAdded , onDocumentModified ו- onDocumentRemoved :

    protected void onDocumentAdded(DocumentChange change) {
        mSnapshots.add(change.getNewIndex(), change.getDocument());
        notifyItemInserted(change.getNewIndex());
    }

    protected void onDocumentModified(DocumentChange change) {
        if (change.getOldIndex() == change.getNewIndex()) {
            // Item changed but remained in same position
            mSnapshots.set(change.getOldIndex(), change.getDocument());
            notifyItemChanged(change.getOldIndex());
        } else {
            // Item changed and changed position
            mSnapshots.remove(change.getOldIndex());
            mSnapshots.add(change.getNewIndex(), change.getDocument());
            notifyItemMoved(change.getOldIndex(), change.getNewIndex());
        }
    }

    protected void onDocumentRemoved(DocumentChange change) {
        mSnapshots.remove(change.getOldIndex());
        notifyItemRemoved(change.getOldIndex());
    }

ואז קרא לשיטות החדשות האלה מ- onEvent :

    @Override
    public void onEvent(QuerySnapshot documentSnapshots,
                        FirebaseFirestoreException e) {

        // ...

        // Dispatch the event
        for (DocumentChange change : documentSnapshots.getDocumentChanges()) {
            // Snapshot of the changed document
            DocumentSnapshot snapshot = change.getDocument();

            switch (change.getType()) {
                case ADDED:
                    onDocumentAdded(change); // Add this line
                    break;
                case MODIFIED:
                    onDocumentModified(change); // Add this line
                    break;
                case REMOVED:
                    onDocumentRemoved(change); // Add this line
                    break;
            }
        }

        onDataChanged();
    }

לבסוף יישם את שיטת startListening() כדי לצרף את המאזין:

    public void startListening() {
        if (mQuery != null && mRegistration == null) {
            mRegistration = mQuery.addSnapshotListener(this);
        }
    }

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

9e45f40faefce5d0.png

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

8. מיין וסנן נתונים

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

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

67898572a35672a5.png

בואו נערוך את שיטת onFilter() של MainActivity.java . שיטה זו מקבלת אובייקט Filters שהוא אובייקט עוזר שיצרנו כדי ללכוד את הפלט של תיבת הדו-שיח של המסננים. נשנה שיטה זו כדי לבנות שאילתה מהמסננים:

    @Override
    public void onFilter(Filters filters) {
        // Construct basic query
        Query query = mFirestore.collection("restaurants");

        // Category (equality filter)
        if (filters.hasCategory()) {
            query = query.whereEqualTo("category", filters.getCategory());
        }

        // City (equality filter)
        if (filters.hasCity()) {
            query = query.whereEqualTo("city", filters.getCity());
        }

        // Price (equality filter)
        if (filters.hasPrice()) {
            query = query.whereEqualTo("price", filters.getPrice());
        }

        // Sort by (orderBy with direction)
        if (filters.hasSortBy()) {
            query = query.orderBy(filters.getSortBy(), filters.getSortDirection());
        }

        // Limit items
        query = query.limit(LIMIT);

        // Update the query
        mQuery = query;
        mAdapter.setQuery(query);

        // Set header
        mCurrentSearchView.setText(Html.fromHtml(filters.getSearchDescription(this)));
        mCurrentSortByView.setText(filters.getOrderDescription(this));

        // Save filters
        mViewModel.setFilters(filters);
    }

בקטע שלמעלה אנו בונים אובייקט Query על ידי צירוף סעיפי where ו- orderBy כדי להתאים את המסננים הנתונים.

הפעל את האפליקציה שוב ובחר את המסנן הבא כדי להציג את המסעדות הפופולריות ביותר במחיר נמוך:

7a67a8a400c80c50.png

כעת אתה אמור לראות רשימה מסוננת של מסעדות המכילה רק אפשרויות במחיר נמוך:

a670188398c3c59.png

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

9. ארגן נתונים בתתי אוספים

בחלק זה נוסיף דירוגים לאפליקציה כדי שמשתמשים יוכלו לסקור את המסעדות המועדפות (או הפחות מועדפות) עליהם.

אוספים ותתי אוספים

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

כדי לגשת לאוסף משנה, התקשר ל- .collection() במסמך האב:

CollectionReference subRef = mFirestore.collection("restaurants")
        .document("abc123")
        .collection("ratings");

אתה יכול לגשת לאוסף משנה ולשאול שאילתה בדיוק כמו עם אוסף ברמה העליונה, אין מגבלות גודל או שינויים בביצועים. תוכל לקרוא עוד על מודל הנתונים של Firestore כאן .

כתיבת נתונים בעסקה

הוספת Rating לאוסף המתאים דורשת רק קריאה .add() , אך עלינו גם לעדכן את הדירוג הממוצע ומספר הדירוגים של אובייקט Restaurant כדי לשקף את הנתונים החדשים. אם נשתמש בפעולות נפרדות כדי לבצע את שני השינויים הללו, ישנם מספר תנאי מרוץ שעלולים לגרום לנתונים מעודכנים או שגויים.

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

  • קרא את הדירוג הנוכחי של המסעדה וחשב את הדירוג החדש
  • הוסף את הדירוג לאוסף המשנה
  • עדכן את הדירוג הממוצע ומספר הדירוגים של המסעדה

פתח את RestaurantDetailActivity.java והטמיע את הפונקציה addRating :

    private Task<Void> addRating(final DocumentReference restaurantRef,
                                 final Rating rating) {
        // Create reference for new rating, for use inside the transaction
        final DocumentReference ratingRef = restaurantRef.collection("ratings")
                .document();

        // In a transaction, add the new rating and update the aggregate totals
        return mFirestore.runTransaction(new Transaction.Function<Void>() {
            @Override
            public Void apply(Transaction transaction)
                    throws FirebaseFirestoreException {

                Restaurant restaurant = transaction.get(restaurantRef)
                        .toObject(Restaurant.class);

                // Compute new number of ratings
                int newNumRatings = restaurant.getNumRatings() + 1;

                // Compute new average rating
                double oldRatingTotal = restaurant.getAvgRating() *
                        restaurant.getNumRatings();
                double newAvgRating = (oldRatingTotal + rating.getRating()) /
                        newNumRatings;

                // Set new restaurant info
                restaurant.setNumRatings(newNumRatings);
                restaurant.setAvgRating(newAvgRating);

                // Commit to Firestore
                transaction.set(restaurantRef, restaurant);
                transaction.set(ratingRef, rating);

                return null;
            }
        });
    }

addRating() מחזירה Task המייצגת את כל העסקה. onRating() מוסיפים מאזינים למשימה כדי להגיב לתוצאה של העסקה.

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

78fa16cdf8ef435a.png

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

f9e670f40bd615b0.png

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

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

עד כה לא שקלנו את האבטחה של יישום זה. איך נדע שמשתמשים יכולים לקרוא ולכתוב רק את הנתונים הנכונים? מסדי נתונים של Firestore מאובטחים על ידי קובץ תצורה בשם כללי אבטחה .

פתח את הקובץ firestore.rules , אתה אמור לראות את הדברים הבאים:

rules_version = '2';
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;
    }
  }
}

הבה נשנה את הכללים האלה כדי למנוע גישה או שינויים לא רצויים לנתונים, נפתח את הקובץ firestore.rules ונחליף את התוכן בדברים הבאים:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Determine if the value of the field "key" is the same
    // before and after the request.
    function isUnchanged(key) {
      return (key in resource.data)
        && (key in request.resource.data)
        && (resource.data[key] == request.resource.data[key]);
    }

    // Restaurants
    match /restaurants/{restaurantId} {
      // Any signed-in user can read
      allow read: if request.auth != null;

      // Any signed-in user can create
      // WARNING: this rule is for demo purposes only!
      allow create: if request.auth != null;

      // Updates are allowed if no fields are added and name is unchanged
      allow update: if request.auth != null
                    && (request.resource.data.keys() == resource.data.keys())
                    && isUnchanged("name");

      // Deletes are not allowed.
      // Note: this is the default, there is no need to explicitly state this.
      allow delete: if false;

      // Ratings
      match /ratings/{ratingId} {
        // Any signed-in user can read
        allow read: if request.auth != null;

        // Any signed-in user can create if their uid matches the document
        allow create: if request.auth != null
                      && request.resource.data.userId == request.auth.uid;

        // Deletes and updates are not allowed (default)
        allow update, delete: if false;
      }
    }
  }
}

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

כדי לקרוא עוד על כללי אבטחה, בקר בתיעוד .

11. מסקנה

יצרת כעת אפליקציה עם כל התכונות על גבי Firestore. למדת על התכונות החשובות ביותר של Firestore כולל:

  • מסמכים ואוספים
  • קריאה וכתיבה של נתונים
  • מיון וסינון באמצעות שאילתות
  • אוספי משנה
  • עסקאות

למד עוד

כדי להמשיך ללמוד על Firestore, הנה כמה מקומות טובים להתחיל:

אפליקציית המסעדות במעבדת קוד זה התבססה על האפליקציה לדוגמה "Friendly Eats". אתה יכול לעיין בקוד המקור של אותה אפליקציה כאן .

אופציונלי: פרוס לייצור

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

12. (אופציונלי) פרוס את האפליקציה שלך

עד כה האפליקציה הזו הייתה מקומית לחלוטין, כל הנתונים כלולים ב-Firebase Emulator Suite. בחלק זה תלמד כיצד להגדיר את פרויקט Firebase שלך ​​כך שהאפליקציה הזו תעבוד בייצור.

אימות Firebase

במסוף Firebase עבור אל הקטע אימות ולחץ על התחל . נווט אל הכרטיסייה שיטת כניסה ובחר באפשרות דוא"ל/סיסמה מספקים מקומיים .

הפעל את שיטת הכניסה לאימייל/סיסמה ולחץ על שמור .

sign-in-providers.png

Firestore

צור מסד נתונים

נווט אל הקטע Firestore Database של המסוף ולחץ על Create Database :

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

פריסת כללים

כדי לפרוס את כללי האבטחה שכתבת קודם לכן, הפעל את הפקודה הבאה בספריית codelab:

$ firebase deploy --only firestore:rules

פעולה זו תפרוס את התוכן של firestore.rules לפרויקט שלך, אותו תוכל לאשר על ידי ניווט ללשונית כללים במסוף.

פרוס אינדקסים

לאפליקציית FriendlyEats יש מיון וסינון מורכבים הדורשים מספר אינדקסים מורכבים מותאמים אישית. ניתן ליצור אותם ביד במסוף Firebase אך קל יותר לכתוב את ההגדרות שלהם בקובץ firestore.indexes.json ולפרוס אותם באמצעות Firebase CLI.

אם תפתח את הקובץ firestore.indexes.json תראה שהאינדקסים הנדרשים כבר סופקו:

{
  "indexes": [
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "city", "mode": "ASCENDING" },
        { "fieldPath": "avgRating", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "category", "mode": "ASCENDING" },
        { "fieldPath": "avgRating", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "price", "mode": "ASCENDING" },
        { "fieldPath": "avgRating", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "city", "mode": "ASCENDING" },
        { "fieldPath": "numRatings", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "category", "mode": "ASCENDING" },
        { "fieldPath": "numRatings", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "price", "mode": "ASCENDING" },
        { "fieldPath": "numRatings", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "city", "mode": "ASCENDING" },
        { "fieldPath": "price", "mode": "ASCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "fields": [
        { "fieldPath": "category", "mode": "ASCENDING" },
        { "fieldPath": "price", "mode": "ASCENDING" }
      ]
    }
  ],
  "fieldOverrides": []
}

כדי לפרוס את האינדקסים האלה, הפעל את הפקודה הבאה:

$ firebase deploy --only firestore:indexes

שים לב שיצירת האינדקס אינה מיידית, אתה יכול לעקוב אחר ההתקדמות במסוף Firebase.

הגדר את האפליקציה

במחלקה FirebaseUtil הגדרנו את Firebase SDK להתחבר לאמולטורים במצב ניפוי באגים:

public class FirebaseUtil {

    /** Use emulators only in debug builds **/
    private static final boolean sUseEmulators = BuildConfig.DEBUG;

    // ...
}

אם תרצה לבדוק את האפליקציה שלך עם פרויקט Firebase האמיתי שלך, תוכל:

  1. בנה את האפליקציה במצב שחרור והפעל אותה במכשיר.
  2. שנה זמנית את sUseEmulators ל- false והפעל שוב את האפליקציה.

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