> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
| `source` | `text` | URI אופציונלי המקשר למידע על מקור בגרף הידע. מחרוזת ריקה או NULL מציינים שאין מקור. |
#### טיפול באינדקסים
כל שורה מאוחסנת מספר פעמים - פעם אחת עבור כל שדה מאומדד המוגדר בסכימה. שדות המפתח הראשוניים מטופלים כאינדקס ללא סימון מיוחד, מה שמספק גמישות עתידית.
**דוגמה לאינדקס של שדה בודד:**
הסכימה מגדירה את `email` כמאומדד
`index_name = "email"`
`index_value = ['foo@bar.com']`
**דוגמה לאינדקס מורכב:**
הסכימה מגדירה אינדקס מורכב על `region`ו-`status`
`index_name = "region,status"` (שמות השדות ממוינים ומחוברים באמצעות פסיק)
`index_value = ['US', 'active']` (הערכים באותו סדר כמו שמות השדות)
**דוגמה למפתח ראשי:**
הסכימה מגדירה את `customer_id` כמפתח ראשי
`index_name = "customer_id"`
`index_value = ['CUST001']`
#### תבניות שאילתה
כל השאילתות עוקבות אחר אותו תבנית, ללא קשר לאיזה אינדקס משתמשים:
```sql
SELECT * FROM rows
WHERE collection = 'import_2024'
AND schema_name = 'customers'
AND index_name = 'email'
AND index_value = ['foo@bar.com']
```
#### פשרות עיצוביות
**יתרונות:**
שינויים בסכימה אינם מחייבים שינויים במבנה הטבלה
נתוני השורה אינם גלויים ל-Cassandra - הוספות/הסרות שדות הן שקופות
דפוס שאילתות עקבי לכל שיטות הגישה
אין אינדקסים משניים של Cassandra (שיכולים להיות איטיים בקנה מידה גדול)
סוגי Cassandra מקוריים בכל מקום (`map`, `frozen<list>`)
**פשרות:**
הגברה בכתיבה: כל הוספת שורה = N הוספות (אחת לכל שדה מועדן)
תקורה של אחסון עקב שכפול נתוני שורה
מידע על סוגים מאוחסן בתצורת הסכימה, המרה בשכבת האפליקציה
#### מודל עקביות
העיצוב מקבל מספר פישוטים:
1.**אין עדכוני שורות**: המערכת היא רק להוספה. זה מבטל חששות לגבי עקביות בעדכון עותקים מרובים של אותה שורה.
2.**סובלנות לשינויי סכימה**: כאשר הסכימות משתנות (לדוגמה, הוספת/הסרת אינדקסים), שורות קיימות שומרות על האינדוקס המקורי שלהן. שורות ישנות לא יהיו ניתנות לגילוי באמצעות אינדקסים חדשים. משתמשים יכולים למחוק וליצור מחדש סכימה כדי להבטיח עקביות במידת הצורך.
### מעקב ומחיקת מחיצות
#### הבעיה
עם מפתח המחיצה `(collection, schema_name, index_name)`, מחיקה יעילה דורשת ידיעת כל מפתחות המחיצה למחיקה. מחיקה רק לפי `collection` או `collection + schema_name` דורשת ידיעת כל ערכי `index_name` שיש להם נתונים.
כותב השורות שומר מטמון בזיכרון של זוגות `(collection, schema_name)` רשומים. בעת עיבוד שורה:
1. בדוק אם `(collection, schema_name)` נמצא במטמון
2. אם לא שמור במטמון (השורה הראשונה עבור זוג זה):
חפש את תצורת הסכימה כדי לקבל את כל שמות האינדקסים
הכנס ערכים ל-`row_partitions` עבור כל `(collection, schema_name, index_name)`
הוסף את הזוג למטמון
3. המשך בכתיבת נתוני השורה
כותב השורות גם עוקב אחר אירועי שינוי בתצורת הסכימה. כאשר סכימה משתנה, רשומות מטמון רלוונטיות נמחקים כך שהשורה הבאה תגרום לרישום מחדש עם שמות האינדקסים המעודכנים.
גישה זו מבטיחה:
כתיבות לטבלת חיפוש מתרחשות פעם אחת לכל זוג `(collection, schema_name)`, ולא לכל שורה
טבלת החיפוש משקפת את האינדקסים שהיו פעילים בעת כתיבת הנתונים
שינויי סכימה במהלך הייבוא מזוהים כראוי
#### פעולות מחיקה
**מחיקת אוסף:**
```sql
-- 1. Discover all partitions
SELECT schema_name, index_name FROM row_partitions WHERE collection = 'X';
-- 2. Delete each partition from rows table
DELETE FROM rows WHERE collection = 'X' AND schema_name = '...' AND index_name = '...';
-- (repeat for each discovered partition)
-- 3. Clean up the lookup table
DELETE FROM row_partitions WHERE collection = 'X';
```
**מחיקת אוסף וסכימה:**
```sql
-- 1. Discover partitions for this schema
SELECT index_name FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y';
-- 2. Delete each partition from rows table
DELETE FROM rows WHERE collection = 'X' AND schema_name = 'Y' AND index_name = '...';
-- (repeat for each discovered partition)
-- 3. Clean up the lookup table entries
DELETE FROM row_partitions WHERE collection = 'X' AND schema_name = 'Y';
```
### הטמעות שורות
הטמעות שורות מאפשרות התאמה סמנטית/עמומה על ערכים מוענקים, תוך פתרון בעיית אי ההתאמה בשפה טבעית (לדוגמה, מציאת "CHESTNUT ST" בעת חיפוש עבור "Chestnut Street").
#### סקירה כללית של העיצוב
כל ערך מוענק מוטמע ונשמר במאגר וקטורים (Qdrant). בזמן שאילתה, השאילתה מוטמעת, וקטורים דומים נמצאים, ומטא-הנתונים המשויכים משמשים לאחזור השורות בפועל ב-Cassandra.
#### מבנה אוסף Qdrant
אוסף Qdrant אחד לכל טופל `(user, collection, schema_name, dimension)`:
השמות עוברים סינון (תווים שאינם אלפא-נומריים מוחלפים ב-`_`, אותיות קטנות, קידומות מספריות מקבלות קידומת `r_`)
**ההצדקה:** מאפשר מחיקה נקייה של מופע `(user, collection, schema_name)` על ידי מחיקת אוספי Qdrant תואמים; הסיומת של הממד מאפשרת למודלי הטמעה שונים להתקיים יחד.
#### מה מוטמע
הייצוג הטקסטואלי של ערכי אינדקס:
| סוג אינדקס | דוגמה `index_value` | טקסט להטמעה |
הערה: `user`, `collection`ו-`schema_name` משתמעים משם האוסף של Qdrant.
#### זרימת שאילתה
1. משתמש מבקש מידע על "Chestnut Street" בתוך משתמש U, אוסף X, סכימה Y.
2. הטמע את טקסט השאילתה.
3. קבע את שם/שמות האוסף של Qdrant התואמים לפריט `rows_U_X_Y_`.
4. חפש באוספי Qdrant התואמים את הווקטורים הקרובים ביותר.
5. קבל נקודות תואמות עם מטענים המכילים `index_name`ו-`index_value`.
6. שאילתת קסנדרה:
```sql
SELECT * FROM rows
WHERE collection = 'X'
AND schema_name = 'Y'
AND index_name = '<frompayload>'
AND index_value = <frompayload>
```
7. החזרת שורות תואמות
#### אופציונלי: סינון לפי שם אינדקס
שאילתות יכולות, באופן אופציונלי, לסנן לפי `index_name` ב-Qdrant כדי לחפש רק שדות ספציפיים:
**"מצא כל שדה התואם ל-'Chestnut'"** → חיפוש בכל הווקטורים באוסף
**"מצא את street_name התואם ל-'Chestnut'"** → סינון כאשר `payload.index_name = 'street_name'`
#### ארכיטקטורה
הטמעות שורות עוקבות את ה**תבנית בשני שלבים** המשמשת את GraphRAG (graph-embeddings, document-embeddings):
**שלב 1: חישוב הטמעה** (`trustgraph-flow/trustgraph/embeddings/row_embeddings/`) - צורך `ExtractedObject`, מחשב הטמעות באמצעות שירות ההטמעות, מוציא `RowEmbeddings`
**שלב 2: אחסון הטמעה** (`trustgraph-flow/trustgraph/storage/row_embeddings/qdrant/`) - צורך `RowEmbeddings`, כותב וקטורים ל-Qdrant
כותב השורות של Cassandra הוא צרכן מקבילי נפרד:
**כותב שורות Cassandra** (`trustgraph-flow/trustgraph/storage/rows/cassandra`) - צורך `ExtractedObject`, כותב שורות ל-Cassandra
שלושת השירותים צורכים מאותו זרימה, תוך שמירה על הפרדה ביניהם. זה מאפשר:
התאמה עצמאית של כתיבת Cassandra לעומת יצירת הטמעות לעומת אחסון וקטורים
ניתן להשבית שירותי הטמעות אם אינם נחוצים
כשל בשירות אחד לא משפיע על השירותים האחרים
ארכיטקטורה עקבית עם צינורות GraphRAG
#### נתיב כתיבה
**שלב 1 (מעבד הטמעות שורות):** בעת קבלת `ExtractedObject`:
1. חפש את הסכימה כדי למצוא שדות מודדים
2. עבור כל שדה מודד:
בנה את הייצוג הטקסטואלי של ערך האינדקס
חשב הטמעה באמצעות שירות ההטמעות
3. הפק פלט הודעה `RowEmbeddings` המכילה את כל הווקטורים שחושבו
**שלב 2 (כתיבת הטמעות שורות ל-Qdrant):** בעת קבלת `RowEmbeddings`:
1. עבור כל הטמעה בהודעה:
קבע את האוסף של Qdrant מ-`(user, collection, schema_name, dimension)`
מציאת "CHESTNUT ST" כאשר המשתמש מחפש "Chestnut Street"
שליפת נתוני שורה שלמים עם כל השדות
שילוב של דמיון סמנטי עם גישה לנתונים מובנים
### קליטת נתוני שורה
נדחה לשלב מאוחר יותר. יתוכנן יחד עם שינויי קליטה אחרים.
## השפעה על יישום
### ניתוח מצב נוכחי
ליישום הקיים יש שני מרכיבים עיקריים:
| רכיב | מיקום | שורות | תיאור |
|-----------|----------|-------|-------------|
| שירות שאילתות | `trustgraph-flow/trustgraph/query/objects/cassandra/service.py` | ~740 | מונוליטי: יצירת סכימת GraphQL, ניתוח פילטרים, שאילתות Cassandra, טיפול בבקשות |
| כותב | `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py` | ~540 | יצירת טבלאות לפי סכימה, אינדקסים משניים, הוספה/מחיקה |
**דפוס שאילתות נוכחי:**
```sql
SELECT * FROM {keyspace}.o_{schema_name}
WHERE collection = 'X' AND email = 'foo@bar.com'
ALLOW FILTERING
```
**תבנית שאילתה חדשה:**
```sql
SELECT * FROM {keyspace}.rows
WHERE collection = 'X' AND schema_name = 'customers'
AND index_name = 'email' AND index_value = ['foo@bar.com']
```
### שינויים מרכזיים
1.**הפשטת סמנטיקת שאילתות**: הסכימה החדשה תומכת רק בהתאמות מדויקות עבור `index_value`. מסנני ה-GraphQL הנוכחיים (`gt`, `lt`, `contains`, וכו') או:
הופכים לסינון לאחר קבלת הנתונים (אם עדיין נדרש)
מוסרים לטובת שימוש ב-API של הטמעות (embeddings) לביצוע התאמות משוערות
2.**קוד GraphQL משולב הדוק**: ה-`service.py` הנוכחי כולל יצירת טיפוסים של Strawberry, ניתוח מסננים ושאילתות ספציפיות ל-Cassandra. הוספת בסיס נתונים טבלאי נוסף תכפיל כ-400 שורות של קוד GraphQL.
### שינוי מבנה מוצע
השינוי המבני כולל שני חלקים:
#### 1. הפרדת קוד GraphQL
חילוץ רכיבי GraphQL שניתן לעשות בהם שימוש חוזר למודול משותף: