מדדים

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

יש שני סוגים של אינדקסים:

אינדקסים מובנים
כברירת מחדל, מסד נתונים במצב Datastore מגדיר מראש באופן אוטומטי אינדקס לכל מאפיין של כל סוג ישות. האינדקסים האלה של מאפיין יחיד מתאימים לסוגים פשוטים של שאילתות.
אינדקסים מורכבים
אינדקסים מורכבים מאפשרים ליצור אינדקס למספר ערכי מאפיינים לכל ישות באינדקס. אינדקסים מורכבים תומכים בשאילתות מורכבות ומוגדרים בקובץ הגדרות אינדקס (index.yaml).

בהמשך נסביר על סוגי האינדקסים.

הגדרה ומבנה של אינדקס

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

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

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

הגדרת האינדקס

‫Firestore במצב Datastore מספק אינדקסים מובנים, או אוטומטיים, לשאילתות מהסוגים הבאים:

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

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

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

אינדקסים מובנים לא מופיעים בדף Indexes במסוף Google Cloud .

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

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

אינדקסים מורכבים מוגדרים בקובץ הגדרות האינדקס של האפליקציה (index.yaml). (אינדקסים מובנים לא נכללים בקובץ הגדרות האינדקס).

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

אפשר לראות אינדקסים מורכבים בדף Indexes במסוף Google Cloud . אי אפשר להשתמש במסוף Google Cloud כדי ליצור או לעדכן אינדקסים מורכבים.

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

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

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

מידע נוסף על index.yaml זמין במאמר הגדרת אינדקס.

פריסה או מחיקה של אינדקסים

אחרי שמסיימים לשנות את קובץ ההגדרות של האינדקס, מריצים את הפקודה gcloud datastore indexes create כדי להפעיל את האינדקסים. מידע נוסף על עדכון האינדקסים

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

עלויות אחסון וחביון כתיבה

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

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

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

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

ריכזנו כמה נקודות חשובות שכדאי לזכור לגבי אינדקסים והקשר שלהם למאפיינים של הישויות:

מאפיינים עם סוגי ערכים מעורבים

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

חשוב במיוחד לציין את זה במקרה של מספרים שלמים ומספרים בנקודה צפה (floating-point), שמוגדרים כסוגים נפרדים במצב Datastore. מכיוון שכל המספרים השלמים ממוינים לפני כל המספרים העשרוניים, מאפיין עם הערך השלם 38 ממוין לפני מאפיין עם הערך העשרוני 37.5.

מאפיינים שהוחרגו

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

המאפיין description בדוגמה הבאה לא נכלל באינדקסים:

C#

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore C# API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

Entity task = new Entity()
{
    Key = _db.CreateKeyFactory("Task").CreateKey("sampleTask"),
    ["category"] = "Personal",
    ["created"] = new DateTime(1999, 01, 01, 0, 0, 0, DateTimeKind.Utc),
    ["done"] = false,
    ["priority"] = 4,
    ["percent_complete"] = 10.0,
    ["description"] = new Value()
    {
        StringValue = "Learn Cloud Datastore",
        ExcludeFromIndexes = true
    },
};

Go

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Go API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

type Task struct {
	Category        string
	Done            bool
	Priority        int
	Description     string `datastore:",noindex"`
	PercentComplete float64
	Created         time.Time
}
task := &Task{
	Category:        "Personal",
	Done:            false,
	Priority:        4,
	Description:     "Learn Cloud Datastore",
	PercentComplete: 10.0,
	Created:         time.Now(),
}

Java

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Java API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

Entity task =
    Entity.newBuilder(taskKey)
        .set("category", "Personal")
        .set("created", Timestamp.now())
        .set("done", false)
        .set("priority", 4)
        .set("percent_complete", 10.0)
        .set(
            "description",
            StringValue.newBuilder("Learn Cloud Datastore").setExcludeFromIndexes(true).build())
        .build();

Node.js

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Node.js API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

const task = [
  {
    name: 'category',
    value: 'Personal',
  },
  {
    name: 'created',
    value: new Date(),
  },
  {
    name: 'done',
    value: false,
  },
  {
    name: 'priority',
    value: 4,
  },
  {
    name: 'percent_complete',
    value: 10.0,
  },
  {
    name: 'description',
    value: 'Learn Cloud Datastore',
    excludeFromIndexes: true,
  },
];

PHP

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore PHP API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

$task = $datastore->entity(
    $key,
    [
        'category' => 'Personal',
        'created' => new DateTime(),
        'done' => false,
        'priority' => 4,
        'percent_complete' => 10.0,
        'description' => 'Learn Cloud Datastore'
    ],
    ['excludeFromIndexes' => ['description']]
);

Python

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Python API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

from google.cloud import datastore

# For help authenticating your client, visit
# https://cloud.google.com/docs/authentication/getting-started
client = datastore.Client()

import datetime

key = client.key("Task")
task = datastore.Entity(key, exclude_from_indexes=("description",))
task.update(
    {
        "category": "Personal",
        "description": "Learn Cloud Datastore",
        "created": datetime.datetime.now(tz=datetime.timezone.utc),
        "done": False,
        "priority": 4,
        "percent_complete": 10.5,
    }
)
client.put(task)

Ruby

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Ruby API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

task = datastore.entity "Task" do |t|
  t["category"] = "Personal"
  t["created"] = Time.now
  t["done"] = false
  t["priority"] = 4
  t["percent_complete"] = 10.0
  t["description"] = "Learn Cloud Datastore"
  t.exclude_from_indexes! "description", true
end

GQL

לא רלוונטי

השאילתה בדוגמה הבאה לא תחזיר תוצאות אם הנכס description נכלל בהחרגה:

C#

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore C# API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

Query query = new Query("Task")
{
    Filter = Filter.Equal("description", "Learn Cloud Datastore")
};

Go

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Go API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

query := datastore.NewQuery("Tasks").
	FilterField("Description", "=", "A task description")

Java

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Java API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

Query<Entity> query =
    Query.newEntityQueryBuilder()
        .setKind("Task")
        .setFilter(PropertyFilter.eq("description", "A task description"))
        .build();

Node.js

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Node.js API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

const query = datastore
  .createQuery('Task')
  .filter(new PropertyFilter('description', '=', 'A task description.'));

PHP

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore PHP API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

$query = $datastore->query()
    ->kind('Task')
    ->filter('description', '=', 'A task description.');

Python

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Python API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

from google.cloud import datastore

# For help authenticating your client, visit
# https://cloud.google.com/docs/authentication/getting-started
client = datastore.Client()

query = client.query(kind="Task")
query.add_filter(
    filter=datastore.query.PropertyFilter(
        "description", "=", "Learn Cloud Datastore"
    )
)

Ruby

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Ruby API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

query = datastore.query("Task")
                 .where("description", "=", "A task description.")

GQL

# Will not return any results!
SELECT * FROM Task WHERE description = 'A task description.'

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

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

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

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

מגבלות על אינדקסים

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

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

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

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

דוגמה לקוד:

C#

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore C# API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

Entity task = new Entity()
{
    Key = _db.CreateKeyFactory("Task").CreateKey("sampleTask"),
    ["tags"] = new ArrayValue() { Values = { "fun", "programming", "learn" } },
    ["collaborators"] = new ArrayValue() { Values = { "alice", "bob", "charlie" } },
    ["created"] = DateTime.UtcNow
};

Go

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Go API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

task := &Task{
	Tags:          []string{"fun", "programming", "learn"},
	Collaborators: []string{"alice", "bob", "charlie"},
	Created:       time.Now(),
}

Java

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Java API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

Entity task =
    Entity.newBuilder(taskKey)
        .set("tags", "fun", "programming", "learn")
        .set("collaborators", "alice", "bob", "charlie")
        .set("created", Timestamp.now())
        .build();

Node.js

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Node.js API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

const task = {
  method: 'insert',
  key: datastore.key('Task'),
  data: {
    tags: ['fun', 'programming', 'learn'],
    collaborators: ['alice', 'bob', 'charlie'],
    created: new Date(),
  },
};

PHP

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore PHP API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

$task = $datastore->entity(
    $datastore->key('Task'),
    [
        'tags' => ['fun', 'programming', 'learn'],
        'collaborators' => ['alice', 'bob', 'charlie'],
        'created' => new DateTime(),
    ]
);

Python

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Python API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

from google.cloud import datastore

# For help authenticating your client, visit
# https://cloud.google.com/docs/authentication/getting-started
client = datastore.Client()

import datetime

task = datastore.Entity(client.key("Task"))
task.update(
    {
        "tags": ["fun", "programming", "learn"],
        "collaborators": ["alice", "bob", "charlie"],
        "created": datetime.datetime.now(tz=datetime.timezone.utc),
    }
)

Ruby

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Ruby API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

task = datastore.entity "Task" do |t|
  t["tags"] = ["fun", "programming", "learn"]
  t["collaborators"] = ["alice", "bob", "charlie"]
  t["created"] = Time.now
end

GQL

לא רלוונטי

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

‫('fun', 'alice', NOW())
('fun', 'bob', NOW())
('fun', 'charlie', NOW())

‫('programming', 'alice', NOW())
('programming', 'bob', NOW())
('programming', 'charlie', NOW())

‫('learn', 'alice', NOW())
('learn', 'bob', NOW())
('learn', 'charlie', NOW())

אם אותו מאפיין חוזר על עצמו כמה פעמים, מערכת Firestore במצב Datastore יכולה לזהות אינדקסים מתרחבים ולהציע אינדקס חלופי. עם זאת, בכל הנסיבות האחרות (כמו השאילתה שמוגדרת בדוגמה הזו), מסד נתונים במצב Datastore ייצור אינדקס מתפוצץ (exploding index). במקרה כזה, אפשר לעקוף את הבעיה של אינדקס מתפוצץ (exploding index) על ידי הגדרה ידנית של אינדקס בקובץ התצורה של האינדקס:

indexes:
- kind: Task
  properties:
  - name: tags
  - name: created
- kind: Task
  properties:
  - name: collaborators
  - name: created

כך מצמצמים את מספר הרשומות הנדרשות ל-(|tags| * |created| + |collaborators| * |created|), כלומר 6 רשומות במקום 9:

('fun', NOW())
('programming', NOW())
('learn', NOW())

('alice', NOW())
('bob', NOW())
('charlie', NOW())

כל פעולה של commit שתגרום לחריגה ממגבלת הערכים או הגודל של אינדקס תיכשל. בטקסט של השגיאה מפורטות המגבלה שהייתה חריגה ממנה ("Too many indexed properties" או "Index entries too large") והאינדקס המותאם אישית שגרם לכך. אם תיצרו אינדקס חדש שיחרוג מהמגבלות של ישות כלשהי כשהוא ייווצר, שאילתות שיופנו לאינדקס ייכשלו והאינדקס יופיע במצב Error במסוף Google Cloud . כדי לטפל באינדקסים כאלה של Error,

  1. מסירים את האינדקס מקובץ ההגדרות של האינדקס (index.yaml).
  2. באמצעות Google Cloud CLI, מסירים את האינדקס ממסד הנתונים באמצעות הפקודה datastore indexes cleanup, כמו שמתואר במאמר מחיקת אינדקסים שלא בשימוש.
  3. אחת משתי האפשרויות:
    • לנסח מחדש את הגדרת האינדקס ואת השאילתות התואמות, או
    • להסיר את הישויות שגורמות לאינדקס לגדול בצורה מוגזמת.
  4. מוסיפים את האינדקס בחזרה אל index.yaml.
  5. באמצעות Google Cloud CLI, מוסיפים את האינדקס למסד הנתונים על ידי הפעלת הפקודה datastore indexes create, כפי שמתואר במאמר עדכון אינדקסים.

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

מדדים לתחזיות

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

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

SELECT priority, percent_complete FROM Task

SELECT priority, percent_complete, created FROM Task

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

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

SELECT * FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete

שדורש את האינדקס:

indexes:
- kind: Task
  properties:
  - name: priority
  - name: percent_complete

המרת השאילתה הזו לאחת משתי שאילתות ההקרנה

SELECT created FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete

SELECT priority, percent_complete, created FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete

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

indexes:
- kind: Task
  properties:
  - name: priority
  - name: percent_complete
  - name: created

אבל, לפעמים

SELECT priority, percent_complete FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete

לא ישנה את האינדקס הנדרש, כי המאפיינים המוקרנים priority ו-percent_complete כבר נכללו בשאילתה הקיימת.

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

אפשר להשתמש ב-gcloud firestore כדי לנהל אינדקס יחיד במצב Datastore, או להשתמש ב-gcloud datastore עם קובץ index.yaml כדי לנהל את כל האינדקסים במסד נתונים.

gcloud firestore
gcloud firestore indexes composite create --api-scope=datastore-mode-api  --query-scope=QUERY_SCOPE --database=DATABASE_ID
‫gcloud datastore
gcloud alpha datastore indexes create index.yaml --database=DATABASE_ID

מחליפים את מה שכתוב בשדות הבאים:

  • DATABASE_ID: מזהה מסד נתונים.
  • QUERY_SCOPE: הערך collection-recursive לאינדקסים של ישויות אב או collection-group לאינדקסים של ישויות שאינן אב.