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. אפשר ליצור אותו עם שני ערכים מספריים כמו 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, כך ש-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 כערכי מאפייני ישות באמצעות API של msgprop של NDB.
...
...
אם רוצים לשלוח שאילתה לשמות של שדות, צריך ליצור להם אינדקס. אפשר לציין רשימה של שמות שדות שיעברו אינדוקס באמצעות הפרמטר indexed_fields ל-MessageProperty.
MessageProperty תומך בהרבה אפשרויות של נכסים, אבל לא בכולן. הוא תומך ב:
namerepeatedrequireddefaultchoicesvalidatorverbose_name
מאפייני הודעה לא תומכים באפשרות המאפיין indexed, ואי אפשר ליצור אינדקס לערכים של Message. (אפשר ליצור אינדקס לשדות של הודעה כמו שמתואר למעלה).
אפשר גם להשתמש בהודעות מוטמעות (באמצעות MessageField):
...
MessageProperty כולל אפשרות מאפיין מיוחדת, protocol, שמציינת איך אובייקט ההודעה עובר סריאליזציה ל-Datastore. הערכים הם שמות פרוטוקולים כמו אלה שמשמשים את המחלקה 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 יכולים להגדיר מאפיינים באופן דינמי.