שמירת נתונים עם מסד נתונים בזמן אמת של 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 דרך סוג וריאנט התומך ב:

  • אפס (זה מוחק את הנתונים)
  • מספרים שלמים (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;
  });
}

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

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

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

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

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

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

הצעדים הבאים