Catch up on everthing we announced at this year's Firebase Summit. Learn more

שמירת נתונים עם מסד נתונים בזמן אמת של Firebase עבור C ++

להתחיל

ראה Get Started המדריך ראשון אם אתה עדיין לא הקמת אפליקצית הגישה למסד נתון.

קבל מידע על נתונים

כדי לכתוב נתונים למסד הנתונים, אתה צריך מופע של DatabaseReference :

    // Get the root reference location of the database.
    firebase::database::DatabaseReference dbref = database->GetReference();

שמירת נתונים

ישנן ארבע שיטות לכתיבת נתונים למאגר הנתונים בזמן אמת של Firebase:

שיטה שימושים נפוצים
SetValue() כתוב או להחליף נתונים נתיב מוגדר, כגון users/<user-id>/<username> .
PushChild() הוסף לרשימת נתונים. בכל פעם שאתם קוראים Push() , Firebase מייצר מפתח ייחודי שיכול לשמש גם מזהה ייחודי, כגון user-scores/<user-id>/<unique-score-id> .
UpdateChildren() עדכן חלק מהמפתחות לנתיב מוגדר מבלי להחליף את כל הנתונים.
RunTransaction() עדכן נתונים מורכבים שעלולים להיפגם על ידי עדכונים במקביל.

כתוב, עדכן או מחק נתונים בהתייחסות

פעולות כתיבה בסיסיות

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

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

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

dbref.Child("users").Child(userId).Child("username").SetValue(name);

הוסף לרשימת נתונים

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

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

עדכן שדות ספציפיים

כדי לכתוב בו זמנית לילדים ספציפיים של צומת מבלי להחליף צומת ילד אחרים, להשתמש UpdateChildren() השיטה.

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

class LeaderboardEntry {
  std::string uid;
  int score = 0;

 public:
  LeaderboardEntry() {
  }

  LeaderboardEntry(std::string uid, int score) {
    this->uid = uid;
    this->score = score;
  }

  std::map<std::string, Object> ToMap() {
    std::map<string, Variant> result = new std::map<string, Variant>();
    result["uid"] = Variant(uid);
    result["score"] = Variant(score);

    return result;
  }
}

כדי ליצור LeaderboardEntry ובמקביל לעדכן אותו כדי להאכיל הציון האחרון ורשימת הציון של המשתמש עצמו, המשחק משתמש בקוד הבא:

void WriteNewScore(std::string userId, int score) {
  // Create new entry at /user-scores/$userid/$scoreid and at
  // /leaderboard/$scoreid simultaneously
  std::string key = dbref.Child("scores").PushChild().GetKey();
  LeaderBoardEntry entry = new LeaderBoardEntry(userId, score);
  std::map<std::string, Variant> entryValues = entry.ToMap();

  std::map<string, Variant> childUpdates = new std::map<string, Variant>();
  childUpdates["/scores/" + key] = entryValues;
  childUpdates["/user-scores/" + userId + "/" + key] = entryValues;

  dbref.UpdateChildren(childUpdates);
}

דוגמה זו משתמשת PushChild() כדי ליצור רשומה הצומת המכיל ערכים עבור כל המשתמשים /scores/$key ובמקביל לאחזר את המפתח עם key() . המפתח לאחר מכן ניתן להשתמש כדי ליצור ערך שני הציוני של המשתמש על /user-scores/$userid/$key .

באמצעות נתיבים אלה, אתה יכול לבצע עדכונים סימולטני ליעדים רבים בעץ JSON עם שיחה אחת כדי UpdateChildren() , כגון איך בדוגמה זו יוצרת את הרשומה החדשה בשני המקומות. עדכונים סימולטניים שנעשו בצורה זו הם אטומיים: או שכל העדכונים מצליחים או שכל העדכונים נכשלים.

מחק נתונים

הדרך הפשוטה ביותר נתונים המחיקה היא להתקשר RemoveValue() על הפניה למיקום של הנתונים.

אתה יכול גם למחוק ידי ציון null Variant כערך לעוד פעולת הכתיבה כגון SetValue() או UpdateChildren() . אתה יכול להשתמש בטכניקה זו עם UpdateChildren() כדי למחוק ילדים מרובים בשיחת API יחידה.

דע מתי הנתונים שלך מחויבים.

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

שמור נתונים כעסקאות

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

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

void AddScoreToLeaders(std::string email,
                       long score,
                       DatabaseReference leaderBoardRef) {
  leaderBoardRef.RunTransaction([](firebase::database::MutableData* mutableData) {
    if (mutableData.children_count() >= MaxScores) {
      long minScore = LONG_MAX;
      MutableData *minVal = null;
      std::vector<MutableData> children = mutableData.children();
      std::vector<MutableData>::iterator it;
      for (it = children.begin(); it != children.end(); ++it) {
        if (!it->value().is_map())
          continue;
        long childScore = (long)it->Child("score").value().int64_value();
        if (childScore < minScore) {
          minScore = childScore;
          minVal = &*it;
        }
      }
      if (minScore > score) {
        // The new score is lower than the existing 5 scores, abort.
        return kTransactionResultAbort;
      }

      // Remove the lowest score.
      children.Remove(minVal);
    }

    // Add the new high score.
    std::map<std::string, Variant> newScoreMap =
      new std::map<std::string, Variant>();
    newScoreMap["score"] = score;
    newScoreMap["email"] = email;
    children.Add(newScoreMap);
    mutableData->set_value(children);
    return kTransactionResultSuccess;
  });
}

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

כתוב נתונים במצב לא מקוון

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

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

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

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

הצעדים הבאים