דלגו לתוכן

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

מערכת חדשה — 14 יום חינם

כלי נתונים

עודכן 30.08.2026

ששה כלים מכסים את כל העבודה מול הנתונים: שלושה קוראים (Get-Data, Count-Data, Aggregate-Data) ושלושה כותבים (Create-Data, Create-Many, Update-Data).

שולף רשומות מטבלה.

הפרמטר טיפוס חובה המשמעות
table String שם הטבלה (class name), למשל Accounts
where Object תנאי סינון. כל מפתח הוא שדה; מפתחות מרובים מתחברים ב‑AND
keys Array<String> אילו שדות להחזיר (objectId, createdAt ו‑updatedAt חוזרים תמיד). ברירת מחדל — כל השדות
order String שדה למיון; קידומת - למיון יורד, למשל -createdAt
limit Number ברירת מחדל 5, מינימום 1, מקסימום 20000 או 2001 נדחים בוולידציה (Too small / Too big)
skip Number דילוג לצורך עימוד. ברירת מחדל 0
objectId String מזהה רשומה בודדת. בדיוק 10 תווים (9 תווים נדחים בוולידציה). ראו למטה — מבטל את שאר הפרמטרים
JSON
{ "table": "Accounts",
"where": { "IsAccount": false,
"createdAt": { "$gt": { "__type": "Date", "iso": "2026-08-01" } } },
"keys": ["Name", "PhoneNumber", "LeadStatusId"],
"order": "-createdAt",
"limit": 200 }

ברירת המחדל היא 5. לא 100, לא “הכול” — חמש. מודל שפה שמקבל חמש שורות ומדווח “מצאתי 5 לידים החודש” נשמע סמכותי לחלוטין, וטועה בסדר גודל.

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

שימו לב שזה שונה מ‑REST, שם ברירת המחדל 100 ואין תקרה נאכפת על limit (על טבלה בת 2,101 שורות, limit=5000 החזיר את כל 2,101). מי שמעביר קוד בין השכבות מקבל תוצאה אחרת על אותה שאילתה. הכול במקום אחד: מגבלות ומכסות.

מבוסס Parse. אופרטורים: $gt, $lt, $gte, $lte, $ne, $in, $nin, $exists, $regex.

JSON
{
"IsAccount": true,
"City": { "$in": ["תל אביב", "רמת גן"] },
"Total": { "$gte": 10000 },
"ClosedAt": { "$exists": false },
"createdAt": { "$gte": { "__type": "Date", "iso": "2026-01-01T00:00:00.000Z" } },
"OwnerId": { "__type": "Pointer", "className": "_User", "objectId": "2b0QVKoigE" }
}

שתי נקודות שמפילות אנשים:

  1. סינון לפי Pointer דורש את האובייקט המלא{"__type":"Pointer","className":"…","objectId":"…"}. מחרוזת חשופה של ה‑objectId פשוט לא תואמת דבר, בשקט — count: 0 במקום התוצאה האמיתית. בשכבת טפסי web2* זה הפוך: שם Pointer הוא מחרוזת. ראו סוגי נתונים.
  2. תאריך הוא אובייקט עטוף{"__type":"Date","iso":"…"}. מחרוזת תאריך חשופה מושווית כטקסט ומחזירה 0 תוצאות, בלי שגיאה.

שדות Pointer חוזרים בתשובה כאובייקט Pointer — {"__type":"Pointer","className":"SaleStatuses","objectId":"E9cYlAlooc"} — לא כמזהה בודד, אבל גם לא כרשומה המורחבת: אין include. כשצריך את השם של הסטטוס ולא את המזהה — Aggregate-Data עם מסלול Pointer, או שליפה נוספת.

objectId — שליפת רשומה בודדת

Section titled “objectId — שליפת רשומה בודדת”

הסכימה החיה חושפת פרמטר objectId (בדיוק 10 תווים) לשליפת רשומה בודדת. אם הוא חסר ברשימת פרמטרים שראיתם במקום אחר — הסכימה שהשרת מפרסם היא הקובעת.

JSON
{ "table": "Accounts", "objectId": "xK9mP2qRsT" }

סופר רשומות שעונות לתנאי — בלי להחזיר אותן.

הפרמטר טיפוס חובה המשמעות
table String שם הטבלה
where Object אותו תחביר בדיוק כמו ב‑Get-Data
JSON
{ "table": "Accounts",
"where": { "IsAccount": false,
"createdAt": { "$gte": { "__type": "Date", "iso": "2026-08-01T00:00:00.000Z" } } } }

התשובה: {"count": 8}. בלי where — ספירת כל הטבלה.

זול משמעותית מ‑Get-Data, וחסין למלכודת ה‑limit: כשהשאלה היא “כמה”, Count-Data היא התשובה היחידה שאפשר לסמוך עליה. שאלה שנשמעת כמו “כמה לידים נכנסו החודש” ונענית בשליפה — נענית לא נכון.

קיבוץ וצבירה בצד השרת: במקום למשוך 12,000 שורות ולסכם אותן בקוד, השרת מחזיר שורה לכל קבוצה.

הפרמטר טיפוס חובה המשמעות
table String שם הטבלה
group Object { "תווית": { "פונקציה": "שדה" } }. הסכימה מציינת “מאפיין אחד בלבד”, אבל השרת מקבל ומחשב כמה מאפיינים
groupby String | Object לפי מה מקבצים — ראו למטה. חובה (בלי הפרמטר: groupby: Invalid input: expected nonoptional)
where Object סינון לפני הקיבוץ
order String מיון; - לסדר יורד, למשל -total (לפי התווית המחושבת)
limit Number ברירת מחדל 0 = כל השורות, מקסימום 2000 (2001 נדחה בוולידציה)
timeZone String אזור זמן לחישוב חלקי תאריך, למשל Asia/Jerusalem (hour של 10:00Z חוזר 12); ברירת מחדל — UTC של השרת

התשובה: { "results": [ { "_id": <ערך-הקיבוץ>, "<תווית>": <ערך> }, … ] }. ב‑groupby מחרוזת _id הוא הערך עצמו (למשל שם הסטטוס); ב‑groupby אובייקט _id הוא אובייקט עם התוויות שלכם.

הפונקציה מה היא עושה
sum סכום ערכי שדה — {"total":{"sum":"Total"}} · או ספירה{"count":{"sum":1}}
avg ממוצע
min / max הערך הנמוך / הגבוה בקבוצה
first / last הערך הראשון / האחרון בקבוצה

first ו‑last קיימים בסכימה החיה, גם אם הם חסרים ברשימות פונקציות ישנות.

groupby — הסתירה שחשוב להכיר

Section titled “groupby — הסתירה שחשוב להכיר”

הסכימה החיה מתירה שני מבנים:

JSON
// מחרוזת — שדה אחד
{ "table": "Sales", "group": { "total": { "sum": "Total" } },
"groupby": "OwnerId._User.name", "order": "-total", "limit": 10 }
// ⇒ {"results":[{"_id":"דנה לוי","total":3600}]}
// אובייקט — כמה שדות, ותוויות משלכם
{ "table": "Sales", "group": { "total": { "sum": "Total" } },
"groupby": { "month": { "mm": "ClosingDate" },
"status": "SaleStatusId.SaleStatuses.Name" } }
// ⇒ {"results":[{"_id":{"month":1,"status":"חדש"},"total":300}, …]}

מסלול Pointer נכתב FieldName.TargetClassName.TargetFieldNameשם המחלקה באמצע, למשל SaleStatusId.SaleStatuses.Name או OwnerId._User.name. זה בדיוק מה ש‑אגרגציית REST הגולמית לא יודעת לעשות, וזו הסיבה המרכזית להעדיף את הכלי הזה כשצריך שמות ולא מזהים.

חלקי תאריך שאפשר לקבץ לפיהם: hour, dow (יום בשבוע, 1 = ראשון), q (רבעון), q/yy (⇒ {"yy":2026,"q":1}), mm (חודש), mm/yy (⇒ {"yy":2026,"mm":3}), yy. חלק תאריך נכתב תמיד בצורת האובייקט: { "label": { "mm": "ClosingDate" } }.

דוגמה מלאה — הכנסות לפי בעלים

Section titled “דוגמה מלאה — הכנסות לפי בעלים”
JSON
{ "table": "Sales",
"where": { "SaleStatusId": { "__type": "Pointer", "className": "SaleStatuses", "objectId": "zrP1MSVBoq" },
"ClosingDate": { "$gte": { "__type": "Date", "iso": "2026-01-01T00:00:00.000Z" } } },
"group": { "total": { "sum": "Total" } },
"groupby": "OwnerId._User.name",
"order": "-total",
"limit": 10 }

יוצר רשומה אחת.

הפרמטר טיפוס חובה המשמעות
table String שם הטבלה
data Object מפת שדה → ערך
JSON
{ "table": "Tasks",
"data": {
"Name": "לחזור ללקוח",
"DueDate": { "__type": "Date", "iso": "2026-09-01T09:00:00.000Z" },
"AccountId": { "__type": "Pointer", "className": "Accounts", "objectId": "xK9mP2qRsT" },
"OwnerId": { "__type": "Pointer", "className": "_User", "objectId": "2b0QVKoigE" }
} }

התשובה: { "objectId": "LyRGHAc68z", "createdAt": "2026-08-23T11:16:22.956Z" }.

אין ל‑Create-Data דגלי דילוג. טריגרים ירוצו (טריגר create על הטבלה יוצר את רשומת הבת שלו), וכך גם רישום ציר הזמן — אם לטבלה יש הגדרות ציר זמן; השורה ב‑_Timeline נרשמת עם user.objectId === "Master".

יוצר רשומות בכמות. זהו כלי העבודה של כל טעינת נתונים.

הפרמטר טיפוס חובה המשמעות
table String שם הטבלה
data Array<Object> מערך של רשומות, כל אחת כמו ב‑Create-Data
skipTriggers Boolean מדלג על כל טריגרי היצירה של הטבלה (עם הדגל לא נוצרת רשומת הבת של הטריגר; בלעדיו — כן)
skipTimeline Boolean מונע רישום ל‑_Timeline (0 שורות מול 1 בלעדיו)
JSON
{ "table": "Accounts",
"skipTriggers": true,
"data": [
{ "Name": "לקוח א'", "PhoneNumber": "0501234567", "IsAccount": false },
{ "Name": "לקוח ב'", "PhoneNumber": "0507654321", "IsAccount": false }
] }

התשובה היא מערך בסדר הקלט, פריט לכל רשומה:

JSON
[ { "success": { "objectId": "ivgBTJUiUZ", "createdAt": "2026-08-23T11:16:14.069Z" } },
{ "success": { "objectId": "TqbPMxcyAG", "createdAt": "2026-08-23T11:16:14.069Z" } } ]

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

skipTimeline מקטין את יכולת המעקב. השתמשו בו רק כשאתם יודעים למה — יומנים וראיות מסביר מה מאבדים.

גודל אצווה מומלץ: עד ~50 רשומות לקריאה. אין מגבלה מוצהרת בסכימה, ואצוות של 60 ו‑120 רשומות עוברות, אבל תשובה של מאות מזהים מכבידה על הקשר המודל. לסטים גדולים — לולאה של אצוות. ל‑batch של REST מומלצות עד 50 פעולות לקריאה, אבל זו המלצה ולא אכיפה: אצווה של 1,000 פעולות עוברת. דגלי דילוג אין לו בכלל.

מעדכן רשומה אחת קיימת.

הפרמטר טיפוס חובה המשמעות
table String שם הטבלה
objectId String מזהה הרשומה. בדיוק 10 תווים
data Object השדות לעדכון בלבד — שדה שלא נשלח לא נוגעים בו
JSON
{ "table": "Sales", "objectId": "V0sVNyS45K",
"data": {
"SaleStatusId": { "__type": "Pointer", "className": "SaleStatuses", "objectId": "zrP1MSVBoq" },
"Total": { "__op": "Increment", "amount": 500 },
"ClosingDate": { "__type": "Date", "iso": "2026-09-30T00:00:00.000Z" }
} }

התשובה: objectId, updatedAt, והשדות שחושבו בשרת (למשל "Total": 510 אחרי Increment). מזהה שאינו קיים ⇒ Error: Object not found.

{"__op": "Increment", "amount": n} מגדיל שדה מספרי בצד השרת — הדרך הנכונה למונים, כי היא לא מכניסה מרוץ בין קריאה לכתיבה. ערך שלילי מקטין.

אין כלי לעדכון בכמות. עדכון גורף הוא לולאה של Update-Data, או batch ב‑REST.

המלכודת מה קורה ההגנה
limit ברירת מחדל 5 תשובה קטומה שנראית שלמה; אין שגיאה limit מפורש תמיד; Count-Data כששואלים “כמה”
skipTriggers / skipTimeline רק ב‑Master Key בחיבור משתמש הדגל מתעלם בשקט; סופת טריגרים לוודא את שיטת האימות לפני טעינה; Get-Triggers מראש
אין מחיקה תכנון שמניח “ננקה אחר כך” נתקע לתכנן סימון ביטול, לא מחיקה; ניקוי אמיתי — ממשק או REST