דלגו לתוכן

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

מערכת חדשה — 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 התקרה אינה נאכפת — core-api-03). עבדו באצוות של עשרות עד מאות, בלולאה סדרתית — גוף בקשה גדול מדי נופל על 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 (mcp-data-08) — שורה כפולה שנטענה נשארת עד שמישהו ימחק אותה בממשק או ב‑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 רץ לפני כל כתיבה המונית סופת אוטומציות היא בלתי הפיכה
הרשומות שנוצרו נשלפו בחזרה “הצליח” אינו “נשמר נכון”