דלגו לתוכן

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

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

מתכונים — משימות נפוצות דרך MCP

עודכן 30.08.2026

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

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

1. Usage-Guide ← בלי פרמטרים. פעם אחת בסשן.
2. Get-Schema { className: "…" } ← לפני כל נגיעה בטבלה שלא עבדתם עליה בסשן הזה.

Usage-Guide הוא הכלי שהשרת עצמו מורה להתחיל ממנו. הוא מחזיר אובייקט עם שני מפתחות, About Us ו‑How to use, ובשני: מפת טבלאות המערכת (Accounts, _User, _Timeline), כללי מודל הדפים (apps/mybusiness/…, masterPage, rDivider/sDivider), שני מבני התנאים (field/equesition/value ו‑F/C/T/V/P), פעולות כללי הטופס, תחביר ה‑placeholders {{{Name}}} כולל format(date,he-IL,Asia/Jerusalem), והמשאב get-file.

Get-Schema הוא הכלל הראשון של הפלטפורמה:

JSON
{ "className": "Accounts" }

לרשימת שמות הטבלאות בלבד — { "tablesNameOnly": true } בלי className.


מתכון 1 · כמה לידים נכנסו החודש

Section titled “מתכון 1 · כמה לידים נכנסו החודש”

השאלה הכי נפוצה, והתשובה הכי קל לטעות בה.

ליד במערכת הוא שורה ב‑Accounts עם IsAccount: false. לקוח הוא אותה טבלה עם true. זו לא שתי טבלאות — זו טבלה אחת עם דגל.

JSON
// Count-Data
{ "table": "Accounts",
"where": {
"IsAccount": false,
"createdAt": { "$gte": { "__type": "Date", "iso": "2026-08-01T00:00:00.000Z" } }
} }

תשובה אחת — {"count":361} — בלי תלות ב‑limit.

הדרך שנראית נכונה ואינה

Section titled “הדרך שנראית נכונה ואינה”
JSON
// Get-Data — ואז לספור את השורות שחזרו ✗
{ "table": "Accounts", "where": { "IsAccount": false } }
JSON
// Aggregate-Data
{ "table": "Accounts",
"where": {
"IsAccount": false,
"createdAt": { "$gte": { "__type": "Date", "iso": "2026-08-01T00:00:00.000Z" } }
},
"group": { "count": { "sum": 1 } },
"groupby": "LeadStatusId.LeadStatuses.Name",
"order": "-count" }

{"count":{"sum":1}} הוא איך כותבים “ספירה” — אין פונקציית count נפרדת. ה‑groupby עובר דרך ה‑Pointer אל שם הסטטוס, לא אל המזהה שלו. התשובה: {"results":[{"count":353},{"_id":"ליד חדש","count":8}]} — שימו לב לשורה בלי _id: אלה הרשומות שבהן ה‑Pointer ריק. היא תופיע בכל קיבוץ לפי Pointer, וכדאי לתת לה שם בדוח.

כשצריך גם את השורות עצמןGet-Data עם limit מפורש, keys כדי לא לגרור שדות מיותרים, ו‑order:

JSON
{ "table": "Accounts",
"where": { "IsAccount": false,
"createdAt": { "$gte": { "__type": "Date", "iso": "2026-08-01T00:00:00.000Z" } } },
"keys": ["Name", "PhoneNumber", "Email", "LeadStatusId", "createdAt"],
"order": "-createdAt",
"limit": 500 }

מתכון 2 · הכנסות לפי בעלים

Section titled “מתכון 2 · הכנסות לפי בעלים”

הדוגמה הקלאסית שבה מסלול ה‑Pointer של Aggregate-Data מרוויח את מקומו.

JSON
// 1. לוודא שמות שדות
{ "className": "Sales" }
// 2. Aggregate-Data
{ "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 }

תוצאה: עשרת אנשי המכירות המובילים, עם השמות שלהם, בקריאה אחת — {"results":[{"_id":"דנה לוי","total":14850}, …]}.

OwnerId . _User . name
↑ ↑ ↑
שדה מחלקת השדה
בטבלה היעד שאותו
המקור מציגים

שם המחלקה באמצע. דוגמאות נוספות: SaleStatusId.SaleStatuses.Name, AccountId.Accounts.Name. שדות של _User הם באותיות קטנותname, email — בניגוד למוסכמה בשאר הטבלאות.

JSON
{ "table": "Sales",
"where": { "SaleStatusId": { "__type": "Pointer", "className": "SaleStatuses", "objectId": "zrP1MSVBoq" } },
"group": { "total": { "sum": "Total" } },
"groupby": { "month": { "mm": "ClosingDate" } },
"timeZone": "Asia/Jerusalem" }

התשובה: {"results":[{"_id":{"month":1},"total":1500}, …, {"_id":{"month":""},"total":11106}]} — השורה עם month: "" היא המכירות בלי ClosingDate. היא תמיד שם; תנו לה שם או סננו אותה ב‑where.

חלקי תאריך אפשריים: hour, dow, q, q/yy, mm, mm/yy, yy.

timeZone אינו קישוט: בלעדיו החישוב רץ באזור הזמן של השרת, ומכירה שנסגרה ב‑1 בחודש בשעה 01:00 בישראל עלולה ליפול לחודש הקודם.

כמה מדדים בקריאה אחת — עובד, למרות הסכימה. תיאור group אומר “Only one property is allowed”, אבל בפועל: "group": { "total": { "sum": "Total" }, "cnt": { "sum": 1 } } מחזיר את שני המדדים בכל שורה. מאחר שהסכימה מצהירה אחרת, ודאו שכל התוויות חוזרות אם אתם מסתמכים על זה.


מתכון 3 · יבוא מרוכז בלי סופת טריגרים

Section titled “מתכון 3 · יבוא מרוכז בלי סופת טריגרים”

זה המתכון שהכי כדאי לקרוא לפני ולא אחרי.

JSON
// 1. מה בכלל ירוץ כאן?
{ "tableName": "Accounts" } // Get-Triggers
// 2. הסכימה, כדי לדעת מה מותר לשלוח
{ "className": "Accounts" } // Get-Schema
// 3. פתרון ערכי lookup לפני, לא תוך כדי
{ "table": "LeadStatuses", "where": { "Name": "ליד חדש" }, "limit": 1 }
{ "table": "LeadSource", "where": { "Name": "אתר" }, "limit": 1 }
// 4. הטעינה — באצוות
{ "table": "Accounts",
"skipTriggers": true,
"skipTimeline": false,
"data": [
{ "Name": "לקוח א'", "PhoneNumber": "0501234567", "IsAccount": false,
"LeadStatusId": { "__type": "Pointer", "className": "LeadStatuses", "objectId": "e9TwcETDGq" } },
{ "Name": "לקוח ב'", "PhoneNumber": "0507654321", "IsAccount": false,
"LeadStatusId": { "__type": "Pointer", "className": "LeadStatuses", "objectId": "e9TwcETDGq" } }
] }
// 5. אימות
{ "table": "Accounts", "where": { "IsAccount": false, "…": "…" } } // Count-Data

התשובה של Create-Many היא מערך באורך הקלט, פריט לכל רשומה: [{"success":{"objectId":"S0bkiLAr0y","createdAt":"…"}},{"success":{…}}]. שמות טבלאות ה‑lookup כאן — LeadStatuses, LeadSource — ומזהי הסטטוסים הם של סביבת בדיקה; קחו את שלכם מ‑Get-Schema ומשליפה.

בטריגרים שמגיעים עם מערכת vanilla על Accounts (“Lead Conversion Date”, “Account Lead Status” — שניהם על IsAccount: true): עם skipTriggers: true הרשומות נוצרות בלי LeadConversionDate ועם הסטטוס שנשלח; בלעדיו הטריגר רץ, ממלא LeadConversionDate ומחליף את LeadStatusId ל“לקוח”.

שלוש החלטות שחייבות להיסגר מראש

Section titled “שלוש החלטות שחייבות להיסגר מראש”
ההחלטה האפשרויות
טריגרים skipTriggers: true — ואז אתם ממלאים את מה שהטריגר היה ממלא (חותמות זמן, רשומות בת) · או לתת להם לרוץ במודע, אחרי שניטרלתם את פעולות ההתראה לזמן היבוא
ציר הזמן skipTimeline: true מהיר יותר, ומוחק את היכולת להוכיח מה נטען ומתי. ביבוא נתונים ראשוני לרוב משאירים אותו דלוקיומנים וראיות
גודל אצווה לא נמצאה תקרה קשיחה (120 רשומות בקריאה אחת עברו כולן success; גם ב‑REST batch התקרה אינה נאכפת). עבדו באצוות של עשרות עד מאות, בלולאה סדרתית — גוף בקשה גדול מדי נופל על HTTP 413, לא על שגיאת כלי

Create-Many מחזיר את המזהים בסדר שבו שלחתם את הרשומות (data[0][0].success.objectId). זה מה שמאפשר טעינה דו‑שלבית — לידים ואז המכירות שלהם — לפי מיקום:

data[0] → objectId[0] → הליד של שורה 0 בקובץ
data[1] → objectId[1] → הליד של שורה 1
ואז: Create-Many על Sales, עם Pointer ל-objectId המתאים לכל שורה
  • נקו כפילויות במקור. אין Delete-Data — שורה כפולה שנטענה נשארת עד שמישהו ימחק אותה בממשק או ב‑REST עם Master Key.
  • נרמלו טלפונים. מספרים ישראליים מגיעים בעשרות פורמטים; החליטו על אחד לפני הטעינה, לא אחריה.
  • בדקו על 2 שורות קודם. אצווה קטנה, Get-Data על מה שנוצר, ורק אז השאר.

מתכון 4 · מצא‑או‑צור, ואז רשומה מקושרת

Section titled “מתכון 4 · מצא‑או‑צור, ואז רשומה מקושרת”

הזרימה הקנונית של כל אינטגרציה: לוודא שיש איש קשר, ואז לתלות עליו משהו — מכירה, פנייה, משימה, הרשמה.

Get-Schema → חיפוש → קיים? השתמש : צור → צור רשומה מקושרת עם Pointer → אמת
JSON
// Get-Data
{ "table": "Accounts",
"where": { "PhoneNumber": "0501234567" },
"keys": ["Name", "PhoneNumber", "Email", "IsAccount"],
"limit": 5 }

טלפון ישראלי מופיע בפורמטים שונים באותה מערכת — 0501234567, +972501234567, 050-123-4567. השוואה מדויקת על ערך אחד תפספס. אם ההתאמה חשובה, חפשו לפי אימייל, או הריצו כמה שאילתות על הווריאציות. הדפוס שהמוצר עצמו מיישם בקליטת טפסים מתואר בזיהוי כפילויות.

JSON
// Create-Data
{ "table": "Accounts",
"data": {
"Name": "דנה כהן",
"PhoneNumber": "0501234567",
"Email": "dana@example.co.il",
"IsAccount": false
} }

התשובה — { "objectId": "ajBZIKKbyU", "createdAt": "…" } — זה מה שמחזיקים לשלב הבא.

JSON
// Create-Data
{ "table": "Sales",
"data": {
"Name": "הצעה — אתר תדמית",
"AccountId": { "__type": "Pointer", "className": "Accounts", "objectId": "xK9mP2qRsT" },
"OwnerId": { "__type": "Pointer", "className": "_User", "objectId": "2b0QVKoigE" },
"SaleStatusId": { "__type": "Pointer", "className": "SaleStatuses", "objectId": "zrP1MSVBoq" },
"Total": 18500,
"ClosingDate": { "__type": "Date", "iso": "2026-09-30T00:00:00.000Z" }
} }

מזהי הסטטוס (SaleStatusId, LeadStatusId וכו’) אינם קבועים בין מערכות. שולפים אותם פעם אחת בתחילת הסשן ומחזיקים מפה בזיכרון:

JSON
{ "table": "SaleStatuses", "keys": ["Name"], "limit": 100 }
// ⇒ [{"objectId":"E9cYlAlooc","Name":"חדש"}, {"objectId":"zrP1MSVBoq","Name":"הושלמה"}, …]
JSON
// Get-Data על מה שנוצר, עם ה-Pointer
{ "table": "Sales",
"where": { "AccountId": { "__type": "Pointer", "className": "Accounts", "objectId": "xK9mP2qRsT" } },
"keys": ["Name", "Total", "SaleStatusId", "createdAt"],
"order": "-createdAt",
"limit": 5 }

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


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

Section titled “מה לבדוק לפני שסוגרים משימה”
הבדיקה למה
Get-Schema רץ על כל טבלה שנגעתם בה שם שדה שגוי לא מייצר שגיאה
כל Get-Data נושא limit מפורש ברירת המחדל 5
שאלות “כמה” נענו ב‑Count-Data ספירת שורות שחזרו היא ספירה של ה‑limit
כל Pointer וכל תאריך עטופים באובייקט אחרת schema mismatch — ושם שדה שגוי יוצר עמודה בשקט
מזהי lookup נשלפו מהמערכת הזו הם שונים בכל מערכת
Get-Triggers רץ לפני כל כתיבה המונית סופת אוטומציות היא בלתי הפיכה
הרשומות שנוצרו נשלפו בחזרה “הצליח” אינו “נשמר נכון”