Firestore במצב Datastore (Datastore) תומך במגוון סוגי נתונים של ערכי מאפיינים. לדוגמה:
- מספרים שלמים
- מספרים בשיטת נקודה צפה
- מחרוזות
- תאריכים
- נתונים בינאריים
רשימה מלאה של הסוגים זמינה במאמר מאפיינים וסוגי ערכים.
מאפיינים וסוגי ערכים
ערכי הנתונים שמשויכים לישות מורכבים ממאפיין אחד או יותר. לכל מאפיין יש שם וערך אחד או יותר. למאפיין יכולים להיות ערכים מכמה סוגים, ולשתי ישויות יכולים להיות ערכים מסוגים שונים לאותו מאפיין. אפשר להוסיף מאפיינים לאינדקס או להסיר אותם מהאינדקס (שאילתות שממיינות או מסננות לפי מאפיין P יתעלמו מישויות שבהן המאפיין P לא מופיע באינדקס). לישות יכולים להיות לכל היותר 20,000 מאפיינים שעברו אינדוקס.
כששאילתה כוללת נכס עם ערכים מסוגים מעורבים, Datastore משתמש בסדר דטרמיניסטי שמבוסס על הייצוגים הפנימיים:
- ערכי Null
- מספרים עם נקודה קבועה
- מספרים שלמים
- תאריכים ושעות
- ערכים בוליאניים
- רצפים של בייטים
- מחרוזת Unicode
- מפתחות Blobstore
- מפתחות של Datastore
מכיוון ש מחרוזות טקסט ארוכות ומחרוזות ארוכות של בייטים לא עוברות אינדוקס, לא מוגדר להן סדר.
סוגי נכסים
NDB תומך בסוגי המאפיינים הבאים:
| סוג הנכס | תיאור |
|---|---|
IntegerProperty |
מספר שלם חתום ב-64 ביט |
FloatProperty |
מספר בשיטת נקודה צפה עם דיוק כפול |
BooleanProperty |
בוליאני |
StringProperty |
מחרוזת Unicode; עד 1,500 בייט, באינדקס |
TextProperty |
מחרוזת Unicode; אורך בלתי מוגבל, לא נוסף לאינדקס |
BlobProperty |
מחרוזת בייטים לא מפוענחת: אם מגדירים את indexed=True, עד 1,500 בייטים, באינדקס;אם indexed הוא False (ברירת המחדל), אורך בלתי מוגבל, לא באינדקס.ארגומנט אופציונלי של מילת מפתח: compressed. |
DateTimeProperty |
תאריך ושעה (ראו מאפייני תאריך ושעה) |
DateProperty |
תאריך (ראו מאפייני תאריך ושעה) |
TimeProperty |
שעה (ראו מאפייני תאריך ושעה) |
GeoPtProperty |
מיקום גיאוגרפי. זהו אובייקט ndb.GeoPt. לאובייקט יש מאפיינים lat ו-lon, שניהם מסוג float. אפשר ליצור אותו עם שני ערכים מסוג float כמו ndb.GeoPt(52.37, 4.88) או עם מחרוזת ndb.GeoPt("52.37, 4.88"). (זו למעשה אותה כיתה כמו db.GeoPt) |
KeyProperty |
מפתח במאגר הנתונים ארגומנט אופציונלי של מילת מפתח: kind=kind, כדי לדרוש שהמפתחות שמוקצים למאפיין הזה תמיד יהיו מהסוג שצוין. יכול להיות מחרוזת או מחלקה משנית של Model. |
BlobKeyProperty |
מפתח Blobstore מקביל ל- BlobReferenceProperty ב-db API הישן, אבל ערך המאפיין הוא BlobKey ולא BlobInfo. אפשר ליצור BlobInfo ממנו באמצעות BlobInfo(blobkey) |
UserProperty |
אובייקט משתמש. |
StructuredProperty |
כולל סוג אחד של מודל בתוך סוג אחר, לפי ערך (ראו מאפיינים מובנים) |
LocalStructuredProperty |
בדומה ל-StructuredProperty, אבל הייצוג בדיסק הוא blob אטום ולא מתבצע אינדוקס (ראו מאפיינים מובְנים).ארגומנט אופציונלי של מילת מפתח: compressed. |
JsonProperty |
הערך הוא אובייקט Python (כמו רשימה, מילון או מחרוזת) שאפשר לבצע לו סריאליזציה באמצעות המודול json של Python. Datastore מאחסן את הסריאליזציה של ה-JSON כ-blob. לא מתווסף לאינדקס כברירת מחדל.ארגומנט אופציונלי של מילת מפתח: compressed. |
PickleProperty |
הערך הוא אובייקט Python (כמו רשימה, מילון או מחרוזת) שאפשר לבצע לו סריאליזציה באמצעות פרוטוקול ה-pickle של Python. מאגר הנתונים מאחסן את הסריאליזציה של ה-pickle כ-blob. לא מתווסף לאינדקס כברירת מחדל. ארגומנט אופציונלי של מילת מפתח: compressed. |
GenericProperty |
ערך כללי בשימוש בעיקר במחלקה Expando, אבל אפשר להשתמש בו גם באופן מפורש. הסוג יכול להיות כל אחד מהסוגים הבאים: int, long, float, bool, str, unicode, datetime, Key, BlobKey, GeoPt, User, None. |
ComputedProperty |
ערך שמחושב ממאפיינים אחרים על ידי פונקציה בהגדרת המשתמש (UDF). (ראו נכסים מחושבים). |
לחלק מהמאפיינים האלה יש ארגומנט אופציונלי של מילת מפתח, compressed. אם הנכס כולל compressed=True, הנתונים שלו דחוסים באמצעות gzip בדיסק. הוא תופס פחות מקום אבל צריך CPU כדי לבצע קידוד/פענוח בפעולות כתיבה וקריאה.
הדחיסה והפריסה הן "עצלניות"; ערך מאפיין דחוס ייפרס רק בפעם הראשונה שתיגשו אליו. אם קוראים ישות שמכילה ערך מאפיין דחוס וכותבים אותה בחזרה בלי לגשת למאפיין הדחוס, היא לא תעבור דחיסה וגם לא פתיחת דחיסה. גם המטמון בהקשר משתתף בסכימת הטעינה העצלנית הזו, אבל memcache תמיד מאחסן את הערך הדחוס של מאפיינים דחוסים.
בגלל הזמן הנוסף של מעבד המחשב שנדרש לדחיסה, בדרך כלל הכי טוב להשתמש בנכסים דחוסים רק אם הנתונים גדולים מדי ולא יכולים להיכנס בלי דחיסה. חשוב לזכור שדחיסה מבוססת-gzip בדרך כלל לא יעילה לתמונות ולנתוני מדיה אחרים, כי הפורמטים האלה כבר דחוסים באמצעות אלגוריתם דחיסה ספציפי למדיה (למשל, JPEG לתמונות).
אפשרויות הנכס
רוב סוגי הנכסים תומכים בחלק מהארגומנטים הרגילים. הראשון הוא ארגומנט מיקום אופציונלי שמציין את שם Datastore של הנכס. אפשר להשתמש בזה כדי לתת לנכס שם אחר במאגר הנתונים מאשר השם שמופיע מנקודת המבט של האפליקציה. שימוש נפוץ בזה הוא לצמצום הנפח ב-Datastore, כך ש-Datastore ישתמש בשמות מקוצרים של מאפיינים, בזמן שהקוד שלכם ישתמש בשמות ארוכים יותר ובעלי משמעות רבה יותר. לדוגמה,
האפשרות הזו שימושית במיוחד למאפיינים חוזרים שבהם צפויים ערכים רבים לכל ישות.
בנוסף, רוב סוגי הנכסים תומכים בארגומנטים הבאים של מילות מפתח:
| ארגומנט | סוג | ברירת מחדל | תיאור |
|---|---|---|---|
indexed |
bool |
בדרך כלל True |
האם לכלול את הנכס באינדקסים של Datastore. אם הערך הוא False, אי אפשר לשלוח שאילתות לגבי הערכים, אבל פעולות הכתיבה מהירות יותר. לא כל סוגי הנכסים תומכים באינדוקס, ולכן הגדרת indexed ל-True נכשלת עבורם.עלויות פעולות הכתיבה בנכסים לא מפונדקסים נמוכות יותר מאשר בנכסים מפונדקסים. |
repeated |
bool |
False |
ערך המאפיין הוא רשימת Python שמכילה ערכים מהסוג הבסיסי (ראו מאפיינים חוזרים). אי אפשר לשלב אותו עם required=True או default=True. |
required |
bool |
False |
חובה לציין ערך למאפיין. |
default |
סוג הבסיס של הנכס | ללא | ערך ברירת המחדל של המאפיין אם לא צוין ערך מפורש. |
choices |
רשימת הערכים של סוג הבסיס | None |
רשימה אופציונלית של ערכים מותרים. |
validator |
תפקיד | None |
פונקציה אופציונלית לאימות הערך ואולי להמרת הערך. הפונקציה תופעל עם הארגומנטים (prop, value) והיא צריכה להחזיר את הערך (אחרי המרה אפשרית) או להעלות חריגה. קריאה חוזרת לפונקציה על ערך שנכפה לא אמורה לשנות את הערך עוד יותר. (לדוגמה, החזרת value.strip() או value.lower() היא בסדר, אבל לא value + '$'). יכולה גם להחזיר None, שפירושו 'ללא שינוי'. אפשר לעיין גם במאמר בנושא כתיבת מחלקות משנה של מאפיינים |
verbose_name |
מחרוזת | None |
תווית HTML אופציונלית לשימוש במסגרות של טפסים באינטרנט כמו jinja2. |
מאפיינים חוזרים
כל נכס עם repeated=True הופך לנכס חוזר. המאפיין מקבל רשימה של ערכים מהסוג הבסיסי, ולא ערך יחיד. לדוגמה, הערך של מאפיין שמוגדר עם IntegerProperty(repeated=True) הוא רשימה של מספרים שלמים.
יכול להיות שמאגר הנתונים יראה כמה ערכים למאפיין כזה. המערכת יוצרת רשומת אינדקס נפרדת לכל ערך. ההגדרה הזו משפיעה על הסמנטיקה של השאילתה. דוגמה מופיעה במאמר בנושא שאילתות לגבי מאפיינים חוזרים.
בדוגמה הזו נעשה שימוש במאפיין שחוזר על עצמו:
...
כך נוצרת ישות Datastore עם התוכן הבא:
כשמבצעים שאילתה לגבי המאפיין tags, הישות הזו תענה לשאילתה לגבי 'python' או לגבי 'ruby'.
כשמעדכנים מאפיין חוזר, אפשר להקצות לו רשימה חדשה או לשנות את הרשימה הקיימת במקום. כשמקצים רשימה חדשה, המערכת מאמתת מייד את הסוגים של הפריטים ברשימה. סוגי פריטים לא תקינים (לדוגמה, הקצאת [1, 2] ל-art.tags למעלה) מעלים חריגה. כשמשנים את הרשימה, השינוי לא מאומת באופן מיידי. במקום זאת, הערך יאומת כשכותבים את הישות ל-Datastore.
Datastore שומר על הסדר של הפריטים ברשימה במאפיין חוזר, כך שאפשר להקצות משמעות מסוימת לסדר שלהם.
מאפייני תאריך ושעה
יש שלושה סוגים של מאפיינים שבהם אפשר לאחסן ערכים שקשורים לתאריך ולשעה:
DatePropertyTimePropertyDateTimeProperty
הערכים של המאפיינים האלה שייכים לסיווגים המתאימים (date, time, datetime) של מודול datetime Python הרגיל. הפורמט הכללי ביותר מבין השלושה הוא DateTimeProperty, שמציין גם תאריך בלוח השנה וגם שעה ביום. הפורמטים האחרים שימושיים מדי פעם למטרות מיוחדות שבהן נדרש רק תאריך (למשל תאריך לידה) או רק שעה (למשל שעת פגישה). מסיבות טכניות, DateProperty ו-TimeProperty הם תת-מחלקות של DateTimeProperty, אבל לא כדאי להסתמך על יחסי התורשה האלה (חשוב לציין שהם שונים מיחסי התורשה בין המחלקות הבסיסיות שמוגדרות על ידי מודול datetime עצמו).
לכל אחד מהמאפיינים האלה יש שתי אפשרויות נוספות של מילות מפתח בוליאניות:
| אפשרות | תיאור |
|---|---|
auto_now_add |
הגדרת הנכס לתאריך ולשעה הנוכחיים כשיוצרים את הישות. אפשר לשנות את ברירת המחדל של המאפיין הזה באופן ידני. כשהישות מתעדכנת, המאפיין לא משתנה. כדי להגדיר את ההתנהגות הזו, משתמשים ב-auto_now. |
auto_now |
הגדרת המאפיין לתאריך ולשעה הנוכחיים כשיוצרים את הישות ובכל פעם שהיא מתעדכנת. |
אי אפשר לשלב את האפשרויות האלה עם repeated=True. ברירת המחדל של שניהם היא False. אם שניהם מוגדרים כ-True, המדיניות auto_now מקבלת עדיפות. אפשר לשנות את הערך של מאפיין באמצעות auto_now_add=True, אבל לא באמצעות auto_now=True. הערך האוטומטי לא נוצר עד שהישות נכתבת, כלומר האפשרויות האלה לא מספקות ערכי ברירת מחדל דינמיים. (הפרטים האלה שונים מאלה של ה-API הישן של מסד הנתונים).
מאפיינים מובנים
אפשר לבנות את המאפיינים של מודל. לדוגמה, אפשר להגדיר מחלקה של מודל Contact שמכילה רשימה של כתובות, שלכל אחת מהן יש מבנה פנימי.
אפשר לעשות את זה באמצעות מאפיינים מובְנים (סוג StructuredProperty``). לדוגמה:
...
...
כך נוצרת ישות Datastore אחת עם המאפיינים הבאים:
קריאה חוזרת של ישות כזו משחזרת בדיוק את הישות המקורית Contact.
למרות שהמופעים של Address מוגדרים באמצעות אותו תחביר כמו עבור מחלקות מודלים, הם לא ישויות מלאות. אין להם מפתחות משלהם ב-Datastore. אי אפשר לאחזר אותם בנפרד מהיישות Contact שאליה הם שייכים. עם זאת, אפשר להריץ שאילתה באפליקציה כדי לקבל את הערכים של השדות הנפרדים שלה. מידע נוסף זמין במאמר בנושא סינון ערכים של מאפיינים מובנים.
שימו לב ש-address.type, address.street ו-address.city נחשבים למערכים מקבילים מנקודת המבט של Datastore, אבל ספריית NDB מסתירה את ההיבט הזה ובונה את הרשימה המתאימה של מופעי Address.
אפשר לציין את אפשרויות הנכס הרגילות עבור נכסים מובנים (חוץ מ-indexed). שם מאגר הנתונים הוא הארגומנט המיקומי השני במקרה הזה (הראשון הוא מחלקת המודל שמשמשת להגדרת מבנה המשנה).
אם לא צריך לשלוח שאילתה לגבי מאפיינים פנימיים של מבנה משנה, אפשר להשתמש במאפיין מקומי מובנה (LocalStructuredProperty) במקום זאת. אם מחליפים את StructuredProperty ב-LocalStructuredProperty בדוגמה שלמעלה, ההתנהגות של קוד Python נשארת זהה, אבל Datastore רואה רק blob אטום לכל כתובת. הישות guido שנוצרה בדוגמה תאוחסן באופן הבא:
name = 'Guido'
address = <opaque blob for {'type': 'home', 'city': 'Amsterdam'}>
address = <opaque blob for {'type': 'work', 'city': 'SF',
'street': 'Spear St'}>
הישות תוקרא בצורה נכונה. מאחר שהמאפיינים מסוג זה תמיד לא נכללים באינדקס, אי אפשר לשלוח שאילתות לגבי ערכי כתובות.
נכסים מחושבים
מאפיינים מחושבים (ComputedProperty) הם מאפיינים לקריאה בלבד, שהערך שלהם מחושב מתוך ערכים של מאפיינים אחרים באמצעות פונקציה שסופקה על ידי האפליקציה. הערה: מאפיין מחושב תומך רק בסוגים שנתמכים על ידי מאפיינים גנריים. הערך המחושב נכתב ל-Datastore כדי שאפשר יהיה לשלוח אליו שאילתות ולהציג אותו בכלי לצפייה ב-Datastore, אבל המערכת מתעלמת מהערך המאוחסן כשהישות נקראת בחזרה מ-Datastore. במקום זאת, הערך מחושב מחדש על ידי קריאה לפונקציה בכל פעם שהערך מתבקש. לדוגמה:
...
הפעולה הזו מאחסנת ישות עם ערכי המאפיינים הבאים:
אם נשנה את השם ל-'Nickie' ונבקש את הערך של name_lower, הפונקציה תחזיר
'nickie':
מאפייני הודעות של Google Protocol RPC
ספריית Google Protocol RPC משתמשת באובייקטים של Message לנתונים מובְנים. האובייקטים האלה יכולים לייצג בקשות RPC, תגובות או דברים אחרים. NDB מספק API לאחסון אובייקטים של Google Protocol RPC Messageכמאפייני ישות. נניח שאתם מגדירים מחלקת משנה Message:
...
אפשר לאחסן אובייקטים של Note ב-Datastore כערכי מאפיינים של ישויות באמצעות msgprop API של NDB.
...
...
אם רוצים לשלוח שאילתה לשמות של שדות, צריך ליצור להם אינדקס. אפשר לציין רשימה של שמות שדות שיעברו אינדוקס באמצעות הפרמטר indexed_fields עד MessageProperty.
MessageProperty תומך בהרבה אפשרויות של נכסים, אבל לא בכולן. הוא תומך ב:
namerepeatedrequireddefaultchoicesvalidatorverbose_name
מאפייני ההודעה לא תומכים באפשרות המאפיין indexed, ולכן אי אפשר ליצור אינדקס של ערכי Message. (אפשר ליצור אינדקס לשדות של הודעה כמו שמתואר למעלה).
אפשר גם להשתמש בהודעות מוטמעות (באמצעות MessageField):
...
MessageProperty כולל אפשרות מאפיין מיוחדת, protocol, שמציינת איך אובייקט ההודעה עובר סריאליזציה למאגר נתונים. הערכים הם שמות פרוטוקולים כפי שמשמשים במחלקה protorpc.remote.Protocols. הפרוטוקולים הנתמכים הם protobuf ו-protojson. ברירת המחדל היא protobuf.
בנוסף, msgprop מגדיר את EnumProperty, סוג מאפיין שאפשר להשתמש בו כדי לאחסן ערך protorpc.messages.Enum בישות. דוגמה:
...
...
הערך מאוחסן ב-EnumProperty כמספר שלם. למעשה, EnumProperty הוא מחלקת משנה של IntegerProperty. המשמעות היא שאפשר לשנות את השם של ערכי enum בלי לשנות ישויות שכבר נשמרו, אבל אי אפשר לשנות את המספר שלהם.
EnumProperty תומך באפשרויות המאפיין הבאות:
nameindexedrepeatedrequireddefaultchoicesvalidatorverbose_name
מידע על מודלים של ישויות ב-NDB
מודל של ישות NDB יכול להגדיר מאפיינים. מאפייני ישות דומים קצת למשתני נתונים של מחלקות Python, שהם דרך מובנית להחזיק נתונים. הם גם דומים קצת לשדות בסכמת מסד נתונים.
בדרך כלל, אפליקציה מגדירה מודל נתונים על ידי הגדרת מחלקה שיורשת מ-Model עם כמה מאפיינים של מחלקת נכסים. לדוגמה:
...
כאן, username, userid ו-email הם מאפיינים של Account.
יש עוד כמה סוגים של נכסים. חלקם שימושיים להצגת תאריכים ושעות, ויש להם תכונות נוחות של עדכון אוטומטי.
אפליקציה יכולה להתאים את ההתנהגות של מאפיין על ידי ציון אפשרויות במאפיין. האפשרויות האלה יכולות להקל על האימות, להגדיר ערכי ברירת מחדל או לשנות את יצירת האינדקס של השאילתות.
למודל יכולות להיות תכונות מורכבות יותר. מאפיינים חוזרים הם כמו רשימות. מאפיינים מובְנים הם כמו אובייקטים. מאפיינים מחושבים לקריאה בלבד מוגדרים באמצעות פונקציות, ולכן קל להגדיר מאפיין במונחים של מאפיין אחד או יותר. מודלים של Expando יכולים להגדיר מאפיינים באופן דינמי.