יצירת מחבר של תוכן

מחבר תוכן הוא תוכנה שמשמשת למעבר של הנתונים במאגר של הארגון ולאכלוס מקור נתונים. Google מספקת את האפשרויות הבאות לפיתוח מחברי תוכן:

  • ערכת ה-SDK של מחבר התוכן. זו אפשרות טובה אם אתם מתכנתים ב-Java. ה-Content Connector SDK הוא wrapper ל-API ל-REST שמאפשר ליצור מחברים במהירות. כדי ליצור מחבר תוכן באמצעות ה-SDK, קראו את המאמר יצירת מחבר תוכן באמצעות ה-SDK של Content Connector.

  • API ל-REST או ספריות API ברמה נמוכה. כדאי להשתמש באפשרויות האלה אם אתם לא מתכנתים ב-Java, או אם ה-codebase שלכם מתאים יותר ל-API ל-REST או לספרייה. כדי ליצור מחבר תוכן באמצעות API ל-REST, קראו את המאמר יצירת מחבר תוכן באמצעות API ל-REST.

מחבר תוכן אופייני מבצע את המשימות הבאות:

  1. קריאה ועיבוד של פרמטרים של תצורה.
  2. שולפת מקטעים נפרדים של נתונים שניתן להוסיף לאינדקס, שנקראים items, ממאגר התוכן של הצד השלישי.
  3. משלבת רשימות ACL, מטא-נתונים ונתוני תוכן לתוך פריטים שאפשר להוסיף לאינדקס.
  4. הוספת פריטים למקור הנתונים של Cloud Search לאינדקס.
  5. (אופציונלי) מקשיבה לשינוי ההתראות ממאגר התוכן של הצד השלישי. התראות על שינויים מומרות לבקשות להוספה לאינדקס, כדי לשמור על סנכרון של מקור הנתונים של Cloud Search עם מאגר של הצד השלישי. המחבר מבצע את המשימה הזו רק אם המאגר תומך בזיהוי שינויים.

יצירת מחבר תוכן באמצעות Content Connector SDK

בקטעים הבאים מוסבר איך ליצור מחבר תוכן באמצעות ה-SDK של מחבר התוכן.

הגדרת יחסי תלות

כדי להשתמש ב-SDK, צריך לכלול יחסי תלות מסוימים בקובץ ה-build. אפשר ללחוץ על הכרטיסייה כדי לראות את יחסי התלות של סביבת ה-build שלכם:

Maven

<dependency>
<groupId>com.google.enterprise.cloudsearch</groupId>
<artifactId>google-cloudsearch-indexing-connector-sdk</artifactId>
<version>v1-0.0.3</version>
</dependency>

Gradle

compile group: 'com.google.enterprise.cloudsearch',
        name: 'google-cloudsearch-indexing-connector-sdk',
        version: 'v1-0.0.3'

הגדרה של תצורת המחבר

לכל מחבר יש קובץ תצורה שמכיל פרמטרים המשמשים את המחבר, כמו מזהה המאגר שלכם. פרמטרים מוגדרים מצמדי מפתח-ערך, למשל api.sourceId=1234567890abcdef.

ה-SDK של Google Cloud Search מכיל מספר פרמטרים של הגדרה, ש-Google מספקת, שמשמשים את כל המחברים. צריך להצהיר על הפרמטרים הבאים ש-Google מספקת בקובץ התצורה:

  • בשביל מחבר תוכן צריך להצהיר על api.sourceId ו-api.serviceAccountPrivateKeyFile כי הפרמטרים האלה מזהים את מיקום המאגר והמפתח הפרטי שדרוש כדי לגשת למאגר.
  • במחבר זהויות, צריך להצהיר על api.identitySourceId כי הפרמטר הזה מזהה את המיקום של מקור הזהויות החיצוני. אם מסנכרנים משתמשים, צריך גם להצהיר על api.customerId כמזהה הייחודי של חשבון Google Workspace של הארגון.

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

תוכלו גם להגדיר פרמטרים משלכם שספציפיים למאגר, ולהשתמש בהם בקובץ התצורה.

מעבירים את קובץ התצורה למחבר

מגדירים את מאפיין המערכת config כדי להעביר את קובץ התצורה למחבר. אפשר להגדיר את המאפיין באמצעות הארגומנט -D כשמפעילים את המחבר. לדוגמה, הפקודה הבאה מפעילה את המחבר עם קובץ התצורה MyConfig.properties:

java -classpath myconnector.jar;... -Dconfig=MyConfig.properties MyConnector

אם הארגומנט הזה חסר, ערכת ה-SDK תנסה לגשת לקובץ תצורה שמוגדר כברירת מחדל בשם connector-config.properties.

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

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

אסטרטגיית מעבר מלאה

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

אסטרטגיית המעבר הזו מתאימה למאגרים קטנים עם נתונים סטטיים בעיקר ולא היררכיים. כדאי להשתמש באסטרטגיית המעבר הזו גם כאשר זיהוי השינויים קשה או שאינו נתמך על ידי המאגר.

הצגת רשימה של אסטרטגיית מעבר

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

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

מעבר בתרשים

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

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

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

יצירת מחבר מעבר מלא באמצעות מחלקה של תבנית

הקטע הזה במסמכים מתייחס לקטעי קוד מהדוגמה FullTraversalSample.

הטמעת נקודת הכניסה של המחבר

נקודת הכניסה למחבר היא ה-method main(). המשימה העיקרית של השיטה הזו היא ליצור מכונה של המחלקה Application ולהפעיל את ה-method start() שלה כדי להריץ את המחבר.

לפני הקריאה ל-application.start(), צריך להשתמש במחלקה IndexingApplication.Builder כדי ליצור את התבנית FullTraversalConnector. האובייקט FullTraversalConnector מקבל אובייקט Repository שמטמיעים בו methods. קטע הקוד הבא מראה איך להטמיע את ה-method main():

FullTraversalSample.java
/**
 * This sample connector uses the Cloud Search SDK template class for a full
 * traversal connector.
 *
 * @param args program command line arguments
 * @throws InterruptedException thrown if an abort is issued during initialization
 */
public static void main(String[] args) throws InterruptedException {
  Repository repository = new SampleRepository();
  IndexingConnector connector = new FullTraversalConnector(repository);
  IndexingApplication application = new IndexingApplication.Builder(connector, args).build();
  application.start();
}

מאחורי הקלעים, ה-SDK קורא ל-method initConfig() אחרי הפעלת ה-method main() של המחבר Application.build. ה-method initConfig() מבצעת את המשימות הבאות:

  1. שולחת קריאה ל-method Configuation.isInitialized() כדי לוודא שה-Configuration לא אותחל.
  2. מאתחלת אובייקט Configuration עם צמדי מפתח/ערך ש-Google סיפקה. כל צמד מפתח/ערך מאוחסן באובייקט ConfigValue בתוך האובייקט Configuration.

הטמעת הממשק של Repository

המטרה היחידה של האובייקט Repository היא לבצע את המעבר וההוספה לאינדקס של פריטי המאגר. כשמשתמשים בתבנית, צריך לשנות רק methods מסוימות בממשק Repository כדי ליצור מחבר תוכן. השיטות שמחליפים תלויות בתבנית ובאסטרטגיית המעבר שבהם אתם משתמשים. בשביל FullTraversalConnector, משנים את השיטות הבאות:

  • ה-method init(). כדי לבצע הגדרה והפעלה של מאגר נתונים, מחליפים את השיטה init().

  • ה-method getAllDocs(). כדי לעבור ולהוסיף לאינדקס את כל הפריטים במאגר הנתונים, צריך לשנות את השיטה getAllDocs(). ה-method הזה נקרא פעם אחת לכל מעבר מתוזמן (כפי שהוגדר בהגדרות שלכם).

  • (אופציונלי) ה-method getChanges(). אם המאגר תומך בזיהוי שינויים, מבטלים את ה-method getChanges(). השיטה הזו נקראת פעם אחת לכל מעבר מצטבר מתוזמן (כפי שמוגדר בהגדרות שלכם) כדי לאחזר פריטים ששונו ולהוסיף אותם לאינדקס.

  • (אופציונלי) ה-method close(). אם אתם צריכים לבצע ניקוי של המאגר, מחליפים את ה-method close(). לשיטה הזו קוראים פעם אחת במהלך כיבוי המחבר.

כל אחת מה-methods של האובייקט Repository מחזירה אובייקט ApiOperation מסוג כלשהו. אובייקט ApiOperation מבצע פעולה בצורת קריאה יחידה, או אולי כמה, של IndexingService.indexItem() כדי לבצע את הוספת המאגר בפועל לאינדקס.

אחזור פרמטרים מותאמים אישית של הגדרות אישיות

כחלק מהטיפול בתצורת המחבר, תצטרכו לקבל פרמטרים מותאמים אישית מהאובייקט Configuration. בדרך כלל המשימה הזו מתבצעת בשיטה init() של המחלקה Repository.

במחלקה Configuration יש מספר שיטות לקבלת סוגי נתונים שונים ממערך הגדרות אישיות. כל שיטה מחזירה אובייקט ConfigValue. לאחר מכן תוכלו להשתמש ב-method get() של האובייקט ConfigValue כדי לאחזר את הערך בפועל. קטע הקוד הבא, מ-FullTraversalSample, מראה איך לאחזר ערך יחיד של מספר שלם מותאם אישית מאובייקט Configuration:

FullTraversalSample.java
@Override
public void init(RepositoryContext context) {
  log.info("Initializing repository");
  numberOfDocuments = Configuration.getInteger("sample.documentCount", 10).get();
}

כדי לקבל ולנתח פרמטר שמכיל מספר ערכים, צריך להשתמש באחד מהמנתחים של סוג המחלקה Configuration כדי לנתח את הנתונים למקטעי נתונים נפרדים. קטע הקוד הבא, ממחבר המדריך, משתמש ב-method getMultiValue כדי לקבל רשימה של שמות מאגרי GitHub:

GithubRepository.java
ConfigValue<List<String>> repos = Configuration.getMultiValue(
    "github.repos",
    Collections.emptyList(),
    Configuration.STRING_PARSER);

ביצוע מעבר מלא

שינוי מברירת המחדל של getAllDocs() כדי לבצע מעבר מלא והוספה לאינדקס של המאגר. ה-method getAllDocs() מקבלת נקודת ביקורת. נקודת הביקורת משמשת להמשך ההוספה לאינדקס של פריט ספציפי במקרה של הפרעה לתהליך. לכל פריט במאגר, מבצעים את השלבים הבאים באמצעות ה-method: getAllDocs():

  1. מגדירים הרשאות.
  2. מגדירים את המטא-נתונים של הפריט שרוצים להוסיף לאינדקס.
  3. משלבים את המטא-נתונים והפריט לפריט אחד שאפשר להוסיף לאינדקס RepositoryDoc.
  4. אורזים כל פריט שאפשר להוסיף לאינדקס באיטרטור שמוחזר באמצעות ה-method getAllDocs(). שימו לב ש-getAllDocs() מחזיר בפועל אובייקט CheckpointCloseableIterable שהוא איטרציה של אובייקטים ב-ApiOperation. כל אובייקט מייצג בקשת API שבוצעה ב-RepositoryDoc, למשל הוספה שלו לאינדקס.

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

הגדרת ההרשאות לפריט

המאגר משתמש ברשימה של בקרת גישה (ACL) כדי לזהות את המשתמשים או הקבוצות שיש להם גישה לפריט. רשימת ACL היא רשימה של המזהים של קבוצות או של משתמשים שיש להם גישה לפריט.

צריך לשכפל את רשימת ה-ACL שמשמשת את המאגר כדי לוודא שרק המשתמשים שיש להם גישה לפריט יוכלו לראות את הפריט בתוצאת החיפוש. כשמוסיפים פריט לאינדקס, צריך לכלול את ה-ACL של פריט כדי של-Google Cloud Search יהיה את המידע הנדרש כדי לתת לו את רמת הגישה הנכונה.

ה-SDK של מחבר התוכן מספק קבוצה עשירה של מחלקות ושיטות של ACL כדי לבנות מודל של רשימות ה-ACL של רוב המאגרים. אתם צריכים לנתח את ה-ACL של כל פריט במאגר וליצור רשימת ACL תואמת ל-Google Cloud Search כשאתם מוסיפים פריט לאינדקס. אם רשימת ה-ACL של המאגר כוללת מושגים כמו ירושה של ACL, בניית המודלים של רשימת ה-ACL עלולה להיות מורכבת. מידע נוסף על רשימות ACL של Google Cloud Search זמין במאמר רשימות ACL של Google Cloud Search.

הערה: Cloud Search Indexing API תומך ברשימות ACL של דומיין יחיד. היא לא תומכת ברשימות ACL חוצות-דומיינים. משתמשים במחלקה Acl.Builder כדי להגדיר גישה לכל פריט באמצעות ACL. קטע הקוד הבא, שנלקח מדוגמת המעבר המלא, מאפשר לכל המשתמשים או ל'חשבונות המשתמשים' (getCustomerPrincipal()) להיות "קוראים" של כל הפריטים (.setReaders()) בזמן ביצוע החיפוש.

FullTraversalSample.java
// Make the document publicly readable within the domain
Acl acl = new Acl.Builder()
    .setReaders(Collections.singletonList(Acl.getCustomerPrincipal()))
    .build();

חשוב להבין רשימות ACL כדי לבנות מודלים מתאימים של רשימות ACL למאגר. לדוגמה, יכול להיות שאתם מוסיפים לאינדקס קבצים במערכת קבצים שמשתמשת בסוג ירושה כלשהו, שבו תיקיות צאצא יורשות הרשאות מתיקיות הורה. כדי ליצור מודלים של ירושה של רשימות ACL צריך מידע נוסף, שמופיע ברשימות ACL של Google Cloud Search

הגדרת מטא-נתונים של פריט

המטא-נתונים מאוחסנים באובייקט Item. כדי ליצור Item, צריך לפחות מזהה מחרוזת ייחודי, סוג פריט, ACL, כתובת URL וגרסה של הפריט. קטע הקוד הבא מראה איך לפתח Item באמצעות מחלקת העזרה של IndexingItemBuilder.

FullTraversalSample.java
// Url is required. Use google.com as a placeholder for this sample.
String viewUrl = "https://www.google.com";

// Version is required, set to current timestamp.
byte[] version = Longs.toByteArray(System.currentTimeMillis());

// Using the SDK item builder class to create the document with appropriate attributes
// (this can be expanded to include metadata fields etc.)
Item item = IndexingItemBuilder.fromConfiguration(Integer.toString(id))
    .setItemType(IndexingItemBuilder.ItemType.CONTENT_ITEM)
    .setAcl(acl)
    .setSourceRepositoryUrl(IndexingItemBuilder.FieldOrValue.withValue(viewUrl))
    .setVersion(version)
    .build();

יצירת פריט שניתן להוסיף לאינדקס

אחרי שמגדירים את המטא-נתונים של הפריט, אפשר ליצור את הפריט בפועל שניתן להוסיף לאינדקס באמצעות המחלקה RepositoryDoc.Builder. הדוגמה הבאה מראה איך ליצור פריט אחד שניתן להוסיף לאינדקס.

FullTraversalSample.java
// For this sample, content is just plain text
String content = String.format("Hello world from sample doc %d", id);
ByteArrayContent byteContent = ByteArrayContent.fromString("text/plain", content);

// Create the fully formed document
RepositoryDoc doc = new RepositoryDoc.Builder()
    .setItem(item)
    .setContent(byteContent, IndexingService.ContentFormat.TEXT)
    .build();

RepositoryDoc הוא סוג של ApiOperation שמבצע את הבקשה בפועל של IndexingService.indexItem().

אפשר גם להשתמש בשיטה setRequestMode() מהמחלקה RepositoryDoc.Builder כדי לזהות את בקשת ההוספה לאינדקס בתור ASYNCHRONOUS או SYNCHRONOUS:

ASYNCHRONOUS
מצב אסינכרוני גורם לזמן אחזור ארוך יותר להוספה לאינדקס לשרת, ומכסה מכסת תפוקה גדולה לבקשות להוספה לאינדקס. מומלץ להשתמש במצב אסינכרוני לצורך הוספה ראשונית לאינדקס (מילוי חוסרים) של כל המאגר.
SYNCHRONOUS
מצב סינכרוני מאפשר זמן אחזור קצר יותר מהוספה לאינדקס לשרת, ומכסה מכסת תפוקה מוגבלת. מומלץ להשתמש במצב סינכרוני כדי להוסיף לאינדקס עדכונים ושינויים למאגר. אם לא צוין אחרת, ברירת המחדל של מצב הבקשה היא SYNCHRONOUS.

צריך לארוז כל פריט שניתן להוספה לאינדקס באיטרטור

ה-method getAllDocs() מחזירה Iterator, במיוחד CheckpointCloseableIterable, של אובייקטים RepositoryDoc. אפשר להשתמש במחלקה CheckpointClosableIterableImpl.Builder כדי ליצור ולהחזיר איטרטור. קטע הקוד הבא מראה איך ליצור איטרטור ולהחזיר אותו.

FullTraversalSample.java
CheckpointCloseableIterable<ApiOperation> iterator =
  new CheckpointCloseableIterableImpl.Builder<>(allDocs).build();

ה-SDK מפעיל כל קריאה להוספה לאינדקס בתוך האיטרטור.

השלבים הבאים

אפשר לנסות את הפתרונות הבאים:

יצירת מחבר מעבר של רשימה באמצעות מחלקה של תבנית

התור של ההוספה לאינדקס של Cloud Search משמש להחזקה של המזהים וערכי הגיבוב (hash) האופציונליים לכל פריט במאגר. מחבר מעבר רשימה דוחף את מזהי הפריטים לתור ההוספה לאינדקס של Google Cloud Search, ומאחזר אותם אחד בכל פעם לצורך ההוספה לאינדקס. מערכת Google Cloud Search שומרת תורים ומשווה בין תכנים בתור כדי לקבוע את סטטוס הפריטים, למשל אם פריט נמחק מהמאגר. למידע נוסף על התור ליצירת אינדקס ב-Cloud Search, קראו את המאמר תור ההוספה לאינדקס של Cloud Search.

הקטע הזה במסמכים מתייחס לקטעי קוד מהדוגמה ListTraversalSample.

הטמעת נקודת הכניסה של המחבר

נקודת הכניסה למחבר היא ה-method main(). המשימה העיקרית של השיטה הזו היא ליצור מכונה של המחלקה Application ולהפעיל את ה-method start() שלה כדי להריץ את המחבר.

לפני הקריאה ל-application.start(), צריך להשתמש במחלקה IndexingApplication.Builder כדי ליצור את התבנית ListingConnector. ListingConnector מקבל אובייקט Repository שמטמיעים בו methods. קטע הקוד הבא מראה איך להפעיל את ListingConnector ואת Repository המשויכים אליו:

ListTraversalSample.java
/**
 * This sample connector uses the Cloud Search SDK template class for a
 * list traversal connector.
 *
 * @param args program command line arguments
 * @throws InterruptedException thrown if an abort is issued during initialization
 */
public static void main(String[] args) throws InterruptedException {
  Repository repository = new SampleRepository();
  IndexingConnector connector = new ListingConnector(repository);
  IndexingApplication application = new IndexingApplication.Builder(connector, args).build();
  application.start();
}

מאחורי הקלעים, ה-SDK קורא ל-method initConfig() אחרי הפעלת ה-method main() של המחבר Application.build. השיטה initConfig():

  1. שולחת קריאה ל-method Configuation.isInitialized() כדי לוודא שה-Configuration לא אותחל.
  2. מאתחלת אובייקט Configuration עם צמדי מפתח/ערך ש-Google סיפקה. כל צמד מפתח/ערך מאוחסן באובייקט ConfigValue בתוך האובייקט Configuration.

הטמעת הממשק של Repository

המטרה היחידה של האובייקט Repository היא לבצע את המעבר וההוספה לאינדקס של פריטי המאגר. כשמשתמשים בתבנית, צריך לשנות רק methods מסוימות בממשק של Repository כדי ליצור מחבר תוכן. השיטות לשינוי מברירת המחדל תלויות בתבנית ובאסטרטגיית המעבר שבה אתם משתמשים. בשביל ListingConnector, משנים את השיטות הבאות:

  • ה-method init(). כדי לבצע הגדרה והפעלה של מאגר נתונים, מחליפים את השיטה init().

  • ה-method getIds(). כדי לאחזר מזהים וערכי גיבוב (hash) של כל הרשומות במאגר, צריך לבטל את השיטה getIds().

  • ה-method getDoc(). כדי להוסיף פריטים חדשים, לעדכן, לשנות ולמחוק פריטים מהאינדקס, צריך לשנות את השיטה getDoc().

  • (אופציונלי) ה-method getChanges(). אם המאגר תומך בזיהוי שינויים, מבטלים את ה-method getChanges(). השיטה הזו נקראת פעם אחת לכל מעבר מצטבר מתוזמן (כפי שמוגדר בהגדרות שלכם) כדי לאחזר פריטים ששונו ולהוסיף אותם לאינדקס.

  • (אופציונלי) ה-method close(). אם אתם צריכים לבצע ניקוי של המאגר, מחליפים את ה-method close(). לשיטה הזו קוראים פעם אחת במהלך כיבוי המחבר.

כל אחת מה-methods של האובייקט Repository מחזירה אובייקט ApiOperation מסוג כלשהו. אובייקט ApiOperation מבצע פעולה בצורת קריאה יחידה, או אולי כמה, של IndexingService.indexItem() כדי לבצע את הוספת המאגר בפועל לאינדקס.

אחזור פרמטרים מותאמים אישית של הגדרות אישיות

כחלק מהטיפול בתצורת המחבר, תצטרכו לקבל פרמטרים מותאמים אישית מהאובייקט Configuration. בדרך כלל המשימה הזו מתבצעת בשיטה init() של המחלקה Repository.

במחלקה Configuration יש מספר שיטות לקבלת סוגי נתונים שונים ממערך הגדרות אישיות. כל שיטה מחזירה אובייקט ConfigValue. לאחר מכן תוכלו להשתמש ב-method get() של האובייקט ConfigValue כדי לאחזר את הערך בפועל. קטע הקוד הבא, מ-FullTraversalSample, מראה איך לאחזר ערך יחיד של מספר שלם מותאם אישית מאובייקט Configuration:

FullTraversalSample.java
@Override
public void init(RepositoryContext context) {
  log.info("Initializing repository");
  numberOfDocuments = Configuration.getInteger("sample.documentCount", 10).get();
}

כדי לקבל ולנתח פרמטר שמכיל מספר ערכים, צריך להשתמש באחד מהמנתחים של סוג המחלקה Configuration כדי לנתח את הנתונים למקטעי נתונים נפרדים. קטע הקוד הבא, ממחבר המדריך, משתמש ב-method getMultiValue כדי לקבל רשימה של שמות מאגרי GitHub:

GithubRepository.java
ConfigValue<List<String>> repos = Configuration.getMultiValue(
    "github.repos",
    Collections.emptyList(),
    Configuration.STRING_PARSER);

ביצוע המעבר בין הרשימות

משנים את ה-method getIds() כדי לאחזר מזהים וערכי גיבוב (hash) לכל הרשומות במאגר. השיטה getIds() מקבלת נקודת ביקורת. נקודת הביקורת משמשת להמשך ההוספה לאינדקס של פריט מסוים במקרה של הפרעה.

לאחר מכן, מחליפים את השיטה getDoc() כדי לטפל בכל פריט בתור ההוספה לאינדקס של Cloud Search.

דחיפת מזהי פריטים וערכי גיבוב (hash)

שינוי של getIds() כדי לאחזר מהמאגר את מזהי הפריטים ואת ערכי הגיבוב של התוכן המשויכים אליהם. לאחר מכן, צמדים של מזהה וגיבוב נארזים בבקשת פעולה בדחיפה לתור ההוספה לאינדקס של Cloud Search. בדרך כלל, מזהי Root או מזהי ההורה מועברים לפניהם מזהי צאצאים עד לסיום העיבוד של היררכיית הפריטים כולה.

ה-method getIds() מקבלת נקודת ביקורת שמייצגת את הפריט האחרון שנוסף לאינדקס. אפשר להשתמש בנקודת הביקורת כדי להמשיך את ההוספה לאינדקס של פריט מסוים אם התהליך הופסק. בשביל כל פריט במאגר, מבצעים את השלבים הבאים באמצעות השיטה getIds():

  • מקבלים מהמאגר כל מזהה פריט ואת ערך הגיבוב שמשויך אליו.
  • אורזים כל צמד של מזהה וערך גיבוב (hash) ל-PushItems.
  • משלבים כל PushItems באיטרטור שמוחזר באמצעות ה-method getIds(). שימו לב ש-getIds() מחזיר למעשה אובייקט CheckpointCloseableIterable שהוא איטרציה של אובייקטים ב-ApiOperation, כל אובייקט שמייצג בקשת API שבוצעה ב-RepositoryDoc, למשל, דחיפת הפריטים לתור.

קטע הקוד הבא מראה איך לאחזר כל מזהה פריט וערך גיבוב (hash) ולהוסיף אותם ל-PushItems. PushItems היא בקשה של ApiOperation להעברת פריט לתור ההוספה לאינדקס ב-Cloud Search.

ListTraversalSample.java
PushItems.Builder allIds = new PushItems.Builder();
for (Map.Entry<Integer, Long> entry : this.documents.entrySet()) {
  String documentId = Integer.toString(entry.getKey());
  String hash = this.calculateMetadataHash(entry.getKey());
  PushItem item = new PushItem().setMetadataHash(hash);
  log.info("Pushing " + documentId);
  allIds.addPushItem(documentId, item);
}

קטע הקוד הבא מסביר איך להשתמש במחלקה PushItems.Builder כדי לארוז את המזהים ואת ערכי הגיבוב בדחיפה אחת של ApiOperation.

ListTraversalSample.java
ApiOperation pushOperation = allIds.build();
CheckpointCloseableIterable<ApiOperation> iterator =
  new CheckpointCloseableIterableImpl.Builder<>(
      Collections.singletonList(pushOperation))
  .build();
return iterator;

הפריטים מועברים לתור ההוספה לאינדקס של Cloud Search לצורך עיבוד נוסף.

מאחזרים כל פריט ומטפלים בו

כדי לטפל בכל פריט בתור ההוספה לאינדקס של Cloud Search, צריך לשנות את getDoc(). פריט יכול להיות חדש, לשנות אותו, לא השתנה או לא קיים יותר במאגר המקור. מאחזרים ומוסיפים לאינדקס כל פריט חדש או פריט שעבר שינוי. מסירים מהאינדקס פריטים שכבר לא קיימים במאגר המקור.

ה-method getDoc() מקבלת פריט מתור ההוספה לאינדקס של Google Cloud Search. לכל פריט בתור, מבצעים את השלבים הבאים באמצעות ה-method getDoc():

  1. בודקים אם מזהה הפריט, בתור ההוספה לאינדקס של Cloud Search, קיים במאגר. אם לא, מוחקים את הפריט מהאינדקס.

  2. מעיינים באינדקס כדי לברר את סטטוס הפריט, ואם הפריט לא השתנה (ACCEPTED), לא צריך לעשות שום דבר.

  3. האינדקס השתנה או פריטים חדשים:

    1. מגדירים את ההרשאות.
    2. מגדירים את המטא-נתונים של הפריט שרוצים להוסיף לאינדקס.
    3. משלבים את המטא-נתונים והפריט לפריט אחד שאפשר להוסיף לאינדקס RepositoryDoc.
    4. צריך להחזיר את RepositoryDoc.

הערה: התבנית ListingConnector לא תומכת בהחזרה של null בשיטה getDoc(). החזרת null תוביל לNullPointerException.

טיפול בפריטים שנמחקו

קטע הקוד הבא מראה איך לבדוק אם פריט קיים במאגר, ואם לא, למחוק אותו.

ListTraversalSample.java
String resourceName = item.getName();
int documentId = Integer.parseInt(resourceName);

if (!documents.containsKey(documentId)) {
  // Document no longer exists -- delete it
  log.info(() -> String.format("Deleting document %s", item.getName()));
  return ApiOperations.deleteItem(resourceName);
}

documents הוא מבנה נתונים שמייצג את המאגר. אם documentID לא נמצא ב-documents, מחזירים את הערך APIOperations.deleteItem(resourceName) כדי למחוק את הפריט מהאינדקס.

טיפול בפריטים שלא השתנו

קטע הקוד הבא מראה איך לדגום את סטטוס הפריט בתור ההוספה לאינדקס של Cloud Search, ולטפל בפריט שלא השתנה.

ListTraversalSample.java
String currentHash = this.calculateMetadataHash(documentId);
if (this.canSkipIndexing(item, currentHash)) {
  // Document neither modified nor deleted, ack the push
  log.info(() -> String.format("Document %s not modified", item.getName()));
  PushItem pushItem = new PushItem().setType("NOT_MODIFIED");
  return new PushItems.Builder().addPushItem(resourceName, pushItem).build();
}

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

ListTraversalSample.java
/**
 * Checks to see if an item is already up to date
 *
 * @param previousItem Polled item
 * @param currentHash  Metadata hash of the current github object
 * @return PushItem operation
 */
private boolean canSkipIndexing(Item previousItem, String currentHash) {
  if (previousItem.getStatus() == null || previousItem.getMetadata() == null) {
    return false;
  }
  String status = previousItem.getStatus().getCode();
  String previousHash = previousItem.getMetadata().getHash();
  return "ACCEPTED".equals(status)
      && previousHash != null
      && previousHash.equals(currentHash);
}

הגדרת ההרשאות לפריט

המאגר משתמש ברשימה של בקרת גישה (ACL) כדי לזהות את המשתמשים או הקבוצות שיש להם גישה לפריט. רשימת ACL היא רשימה של המזהים של קבוצות או של משתמשים שיש להם גישה לפריט.

צריך לשכפל את רשימת ה-ACL שמשמשת את המאגר כדי לוודא שרק המשתמשים שיש להם גישה לפריט יוכלו לראות את הפריט בתוצאת החיפוש. כשמוסיפים פריט לאינדקס, צריך לכלול את ה-ACL של פריט כדי של-Google Cloud Search יהיה את המידע הנדרש כדי לתת לו את רמת הגישה הנכונה.

ה-SDK של מחבר התוכן מספק קבוצה עשירה של מחלקות ושיטות של ACL כדי לבנות מודל של רשימות ה-ACL של רוב המאגרים. אתם צריכים לנתח את ה-ACL של כל פריט במאגר וליצור רשימת ACL תואמת ל-Google Cloud Search כשאתם מוסיפים פריט לאינדקס. אם רשימת ה-ACL של המאגר כוללת מושגים כמו ירושה של ACL, בניית המודלים של רשימת ה-ACL עלולה להיות מורכבת. מידע נוסף על רשימות ACL של Google Cloud Search זמין במאמר רשימות ACL של Google Cloud Search.

הערה: Cloud Search Indexing API תומך ברשימות ACL של דומיין יחיד. היא לא תומכת ברשימות ACL חוצות-דומיינים. משתמשים במחלקה Acl.Builder כדי להגדיר גישה לכל פריט באמצעות ACL. קטע הקוד הבא, שנלקח מדוגמת המעבר המלא, מאפשר לכל המשתמשים או ל'חשבונות המשתמשים' (getCustomerPrincipal()) להיות "קוראים" של כל הפריטים (.setReaders()) בזמן ביצוע החיפוש.

FullTraversalSample.java
// Make the document publicly readable within the domain
Acl acl = new Acl.Builder()
    .setReaders(Collections.singletonList(Acl.getCustomerPrincipal()))
    .build();

חשוב להבין רשימות ACL כדי לבנות מודלים מתאימים של רשימות ACL למאגר. לדוגמה, יכול להיות שאתם מוסיפים לאינדקס קבצים במערכת קבצים שמשתמשת בסוג ירושה כלשהו, שבו תיקיות צאצא יורשות הרשאות מתיקיות הורה. כדי ליצור מודלים של ירושה של רשימות ACL צריך מידע נוסף, שמופיע ברשימות ACL של Google Cloud Search

הגדרת מטא-נתונים של פריט

המטא-נתונים מאוחסנים באובייקט Item. כדי ליצור Item, צריך לפחות מזהה מחרוזת ייחודי, סוג פריט, ACL, כתובת URL וגרסה של הפריט. קטע הקוד הבא מראה איך לפתח Item באמצעות מחלקת העזרה של IndexingItemBuilder.

ListTraversalSample.java
// Url is required. Use google.com as a placeholder for this sample.
String viewUrl = "https://www.google.com";

// Version is required, set to current timestamp.
byte[] version = Longs.toByteArray(System.currentTimeMillis());

// Set metadata hash so queue can detect changes
String metadataHash = this.calculateMetadataHash(documentId);

// Using the SDK item builder class to create the document with
// appropriate attributes. This can be expanded to include metadata
// fields etc.
Item item = IndexingItemBuilder.fromConfiguration(Integer.toString(documentId))
    .setItemType(IndexingItemBuilder.ItemType.CONTENT_ITEM)
    .setAcl(acl)
    .setSourceRepositoryUrl(IndexingItemBuilder.FieldOrValue.withValue(viewUrl))
    .setVersion(version)
    .setHash(metadataHash)
    .build();

יצירת פריט שניתן להוסיף לאינדקס

אחרי שמגדירים את המטא-נתונים של הפריט, אפשר ליצור את הפריט בפועל שניתן להוסיף לאינדקס באמצעות RepositoryDoc.Builder. הדוגמה הבאה מראה איך ליצור פריט אחד שניתן להוסיף לאינדקס.

ListTraversalSample.java
// For this sample, content is just plain text
String content = String.format("Hello world from sample doc %d", documentId);
ByteArrayContent byteContent = ByteArrayContent.fromString("text/plain", content);

// Create the fully formed document
RepositoryDoc doc = new RepositoryDoc.Builder()
    .setItem(item)
    .setContent(byteContent, IndexingService.ContentFormat.TEXT)
    .build();

RepositoryDoc הוא סוג של ApiOperation שמבצע את הבקשה בפועל IndexingService.indexItem().

אפשר גם להשתמש בשיטה setRequestMode() מהמחלקה RepositoryDoc.Builder כדי לזהות את בקשת ההוספה לאינדקס בתור ASYNCHRONOUS או SYNCHRONOUS:

ASYNCHRONOUS
מצב אסינכרוני גורם לזמן אחזור ארוך יותר להוספה לאינדקס לשרת, ומכסה מכסת תפוקה גדולה לבקשות להוספה לאינדקס. מומלץ להשתמש במצב אסינכרוני לצורך הוספה ראשונית לאינדקס (מילוי חוסרים) של כל המאגר.
SYNCHRONOUS
מצב סינכרוני מאפשר זמן אחזור קצר יותר מהוספה לאינדקס לשרת, ומכסה מכסת תפוקה מוגבלת. מומלץ להשתמש במצב סינכרוני כדי להוסיף לאינדקס עדכונים ושינויים למאגר. אם לא צוין אחרת, ברירת המחדל של מצב הבקשה היא SYNCHRONOUS.

השלבים הבאים

אפשר לנסות את הפתרונות הבאים:

  • (אופציונלי) אפשר להשתמש בשיטה close() כדי לשחרר משאבים לפני ההשבתה.
  • (אופציונלי) יוצרים מחבר זהויות באמצעות ה-SDK של מחבר התוכן.

יצירת מחבר מעבר גרף באמצעות מחלקה של תבנית

התור של ההוספה לאינדקס של Cloud Search משמש להחזקה של המזהים וערכי הגיבוב (hash) האופציונליים לכל פריט במאגר. מחבר מעבר בתרשים דוחף את מזהי הפריטים לתור ההוספה לאינדקס של Google Cloud Search, ומאחזר אותם אחד בכל פעם לצורך ההוספה לאינדקס. מערכת Google Cloud Search שומרת תורים ומשווה בין תכנים בתור כדי לקבוע את סטטוס הפריטים, למשל אם פריט נמחק מהמאגר. למידע נוסף על התור ליצירת אינדקס ב-Cloud Search, קראו את התור של Google Cloud Search לאינדקס.

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

החלק הזה במסמכים מתייחס לקטעי קוד מהדוגמה של GraphTraversalSample.

הטמעת נקודת הכניסה של המחבר

נקודת הכניסה למחבר היא ה-method main(). המשימה העיקרית של השיטה הזו היא ליצור מכונה של המחלקה Application ולהפעיל את ה-method start() שלה כדי להריץ את המחבר.

לפני הקריאה ל-application.start(), צריך להשתמש במחלקה IndexingApplication.Builder כדי ליצור את התבנית ListingConnector. האובייקט ListingConnector מקבל אובייקט Repository שמטמיעים בו methods.

קטע הקוד הבא מראה איך להפעיל את ListingConnector ואת Repository המשויכים אליו:

GraphTraversalSample.java
/**
 * This sample connector uses the Cloud Search SDK template class for a graph
 * traversal connector.
 *
 * @param args program command line arguments
 * @throws InterruptedException thrown if an abort is issued during initialization
 */
public static void main(String[] args) throws InterruptedException {
  Repository repository = new SampleRepository();
  IndexingConnector connector = new ListingConnector(repository);
  IndexingApplication application = new IndexingApplication.Builder(connector, args).build();
  application.start();
}

מאחורי הקלעים, ה-SDK קורא ל-method initConfig() אחרי הפעלת ה-method main() של המחבר Application.build. השיטה initConfig():

  1. שולחת קריאה ל-method Configuation.isInitialized() כדי לוודא שה-Configuration לא אותחל.
  2. מאתחלת אובייקט Configuration עם צמדי מפתח/ערך ש-Google סיפקה. כל צמד מפתח/ערך מאוחסן באובייקט ConfigValue בתוך האובייקט Configuration.

הטמעת הממשק של Repository

המטרה היחידה של האובייקט Repository היא לבצע את המעבר וההוספה לאינדקס של פריטי המאגר. כשמשתמשים בתבנית, צריך לשנות רק methods מסוימות בממשק של Repository כדי ליצור מחבר תוכן. השיטות שמחליפים תלויות בתבנית ובאסטרטגיית המעבר שבה אתם משתמשים. בשביל ListingConnector אפשר לשנות את השיטות הבאות:

  • ה-method init(). כדי לבצע הגדרה והפעלה של מאגר נתונים, מחליפים את השיטה init().

  • ה-method getIds(). כדי לאחזר מזהים וערכי גיבוב (hash) של כל הרשומות במאגר, צריך לבטל את השיטה getIds().

  • ה-method getDoc(). כדי להוסיף פריטים חדשים, לעדכן, לשנות ולמחוק פריטים מהאינדקס, צריך לשנות את השיטה getDoc().

  • (אופציונלי) ה-method getChanges(). אם המאגר תומך בזיהוי שינויים, מבטלים את ה-method getChanges(). השיטה הזו נקראת פעם אחת לכל מעבר מצטבר מתוזמן (כפי שמוגדר בהגדרות שלכם) כדי לאחזר פריטים ששונו ולהוסיף אותם לאינדקס.

  • (אופציונלי) ה-method close(). אם אתם צריכים לבצע ניקוי של המאגר, מחליפים את ה-method close(). לשיטה הזו קוראים פעם אחת במהלך כיבוי המחבר.

כל אחת מה-methods של האובייקט Repository מחזירה אובייקט ApiOperation מסוג כלשהו. אובייקט ApiOperation מבצע פעולה בצורת קריאה אחת, או אולי מספר, של IndexingService.indexItem(), כדי לבצע את ההוספה של המאגר בפועל לאינדקס.

אחזור פרמטרים מותאמים אישית של הגדרות אישיות

כחלק מהטיפול בתצורת המחבר, תצטרכו לקבל פרמטרים מותאמים אישית מהאובייקט Configuration. בדרך כלל המשימה הזו מתבצעת בשיטה init() של המחלקה Repository.

במחלקה Configuration יש מספר שיטות לקבלת סוגי נתונים שונים ממערך הגדרות אישיות. כל שיטה מחזירה אובייקט ConfigValue. לאחר מכן תוכלו להשתמש ב-method get() של האובייקט ConfigValue כדי לאחזר את הערך בפועל. קטע הקוד הבא, מ-FullTraversalSample, מראה איך לאחזר ערך יחיד של מספר שלם מותאם אישית מאובייקט Configuration:

FullTraversalSample.java
@Override
public void init(RepositoryContext context) {
  log.info("Initializing repository");
  numberOfDocuments = Configuration.getInteger("sample.documentCount", 10).get();
}

כדי לקבל ולנתח פרמטר שמכיל מספר ערכים, צריך להשתמש באחד מהמנתחים של סוג המחלקה Configuration כדי לנתח את הנתונים למקטעי נתונים נפרדים. קטע הקוד הבא, ממחבר המדריך, משתמש ב-method getMultiValue כדי לקבל רשימה של שמות מאגרי GitHub:

GithubRepository.java
ConfigValue<List<String>> repos = Configuration.getMultiValue(
    "github.repos",
    Collections.emptyList(),
    Configuration.STRING_PARSER);

בצעו את המעבר בגרף

משנים את ה-method getIds() כדי לאחזר מזהים וערכי גיבוב (hash) לכל הרשומות במאגר. השיטה getIds() מקבלת נקודת ביקורת. נקודת הביקורת משמשת להמשך ההוספה לאינדקס של פריט מסוים במקרה של הפרעה.

לאחר מכן, מחליפים את השיטה getDoc() כדי לטפל בכל פריט בתור ההוספה לאינדקס של Cloud Search.

דחיפת מזהי פריטים וערכי גיבוב (hash)

שינוי של getIds() כדי לאחזר מהמאגר את מזהי הפריטים ואת ערכי הגיבוב של התוכן המשויכים אליהם. לאחר מכן, צמדים של מזהה וגיבוב נארזים בבקשת פעולה בדחיפה לתור ההוספה לאינדקס של Cloud Search. בדרך כלל, מזהי Root או מזהי ההורה מועברים לפניהם מזהי צאצאים עד לסיום העיבוד של היררכיית הפריטים כולה.

ה-method getIds() מקבלת נקודת ביקורת שמייצגת את הפריט האחרון שנוסף לאינדקס. אפשר להשתמש בנקודת הביקורת כדי להמשיך את ההוספה לאינדקס של פריט מסוים אם התהליך הופסק. בשביל כל פריט במאגר, מבצעים את השלבים הבאים באמצעות השיטה getIds():

  • מקבלים מהמאגר כל מזהה פריט ואת ערך הגיבוב שמשויך אליו.
  • אורזים כל צמד של מזהה וערך גיבוב (hash) ל-PushItems.
  • משלבים כל PushItems באיטרטור שמוחזר באמצעות ה-method getIds(). שימו לב ש-getIds() מחזיר למעשה אובייקט CheckpointCloseableIterable שהוא איטרציה של אובייקטים ב-ApiOperation, כל אובייקט שמייצג בקשת API שבוצעה ב-RepositoryDoc, למשל, דחיפת הפריטים לתור.

קטע הקוד הבא מראה איך לאחזר כל מזהה פריט וערך גיבוב (hash) ולהוסיף אותם ל-PushItems. PushItems היא בקשה של ApiOperation להעברת פריט לתור ההוספה לאינדקס ב-Cloud Search.

GraphTraversalSample.java
PushItems.Builder allIds = new PushItems.Builder();
PushItem item = new PushItem();
allIds.addPushItem("root", item);

קטע הקוד הבא מסביר איך להשתמש במחלקה PushItems.Builder כדי לארוז את המזהים ואת ערכי הגיבוב בדחיפה אחת ApiOperation.

GraphTraversalSample.java
ApiOperation pushOperation = allIds.build();
CheckpointCloseableIterable<ApiOperation> iterator =
  new CheckpointCloseableIterableImpl.Builder<>(
      Collections.singletonList(pushOperation))
  .build();

הפריטים מועברים לתור ההוספה לאינדקס של Cloud Search לצורך עיבוד נוסף.

מאחזרים כל פריט ומטפלים בו

כדי לטפל בכל פריט בתור ההוספה לאינדקס של Cloud Search, צריך לשנות את getDoc(). פריט יכול להיות חדש, לשנות אותו, לא השתנה או לא קיים יותר במאגר המקור. מאחזרים ומוסיפים לאינדקס כל פריט חדש או פריט שעבר שינוי. מסירים מהאינדקס פריטים שכבר לא קיימים במאגר המקור.

ה-method getDoc() מקבלת פריט מהתור להוספה לאינדקס של Cloud Search. לכל פריט בתור, מבצעים את השלבים הבאים באמצעות ה-method getDoc():

  1. בודקים אם מזהה הפריט, בתור ההוספה לאינדקס של Cloud Search, קיים במאגר. אם לא, מוחקים את הפריט מהאינדקס. אם הפריט קיים, ממשיכים לשלב הבא.

  2. האינדקס השתנה או פריטים חדשים:

    1. מגדירים את ההרשאות.
    2. מגדירים את המטא-נתונים של הפריט שרוצים להוסיף לאינדקס.
    3. משלבים את המטא-נתונים והפריט לפריט אחד שאפשר להוסיף לאינדקס RepositoryDoc.
    4. צריך למקם את מזהי הצאצאים בתור ליצירת אינדקס ב-Cloud Search לצורך עיבוד נוסף.
    5. צריך להחזיר את RepositoryDoc.

טיפול בפריטים שנמחקו

קטע הקוד הבא מראה איך לבדוק אם פריט קיים באינדקס ולמחוק אותו.

GraphTraversalSample.java
String resourceName = item.getName();
if (documentExists(resourceName)) {
  return buildDocumentAndChildren(resourceName);
}
// Document doesn't exist, delete it
log.info(() -> String.format("Deleting document %s", resourceName));
return ApiOperations.deleteItem(resourceName);

הגדרת ההרשאות לפריט

המאגר משתמש ברשימה של בקרת גישה (ACL) כדי לזהות את המשתמשים או הקבוצות שיש להם גישה לפריט. רשימת ACL היא רשימה של המזהים של קבוצות או של משתמשים שיש להם גישה לפריט.

צריך לשכפל את רשימת ה-ACL שמשמשת את המאגר כדי לוודא שרק המשתמשים שיש להם גישה לפריט יוכלו לראות את הפריט בתוצאת החיפוש. כשמוסיפים פריט לאינדקס, צריך לכלול את ה-ACL של פריט כדי של-Google Cloud Search יהיה את המידע הנדרש כדי לתת לו את רמת הגישה הנכונה.

ה-SDK של מחבר התוכן מספק קבוצה עשירה של מחלקות ושיטות של ACL כדי לבנות מודל של רשימות ה-ACL של רוב המאגרים. אתם צריכים לנתח את ה-ACL של כל פריט במאגר וליצור רשימת ACL תואמת ל-Google Cloud Search כשאתם מוסיפים פריט לאינדקס. אם רשימת ה-ACL של המאגר כוללת מושגים כמו ירושה של ACL, בניית המודלים של רשימת ה-ACL עלולה להיות מורכבת. מידע נוסף על רשימות ACL של Google Cloud Search זמין במאמר רשימות ACL של Google Cloud Search.

הערה: Cloud Search Indexing API תומך ברשימות ACL של דומיין יחיד. היא לא תומכת ברשימות ACL חוצות-דומיינים. משתמשים במחלקה Acl.Builder כדי להגדיר גישה לכל פריט באמצעות ACL. קטע הקוד הבא, שנלקח מדוגמת המעבר המלא, מאפשר לכל המשתמשים או ל'חשבונות המשתמשים' (getCustomerPrincipal()) להיות "קוראים" של כל הפריטים (.setReaders()) בזמן ביצוע החיפוש.

FullTraversalSample.java
// Make the document publicly readable within the domain
Acl acl = new Acl.Builder()
    .setReaders(Collections.singletonList(Acl.getCustomerPrincipal()))
    .build();

חשוב להבין רשימות ACL כדי לבנות מודלים מתאימים של רשימות ACL למאגר. לדוגמה, יכול להיות שאתם מוסיפים לאינדקס קבצים במערכת קבצים שמשתמשת בסוג ירושה כלשהו, שבו תיקיות צאצא יורשות הרשאות מתיקיות הורה. כדי ליצור מודלים של ירושה של רשימות ACL צריך מידע נוסף, שמופיע ברשימות ACL של Google Cloud Search

הגדרת מטא-נתונים של פריט

המטא-נתונים מאוחסנים באובייקט Item. כדי ליצור Item, צריך לפחות מזהה מחרוזת ייחודי, סוג פריט, ACL, כתובת URL וגרסה של הפריט. קטע הקוד הבא מראה איך לפתח Item באמצעות מחלקת העזרה של IndexingItemBuilder.

GraphTraversalSample.java
// Url is required. Use google.com as a placeholder for this sample.
String viewUrl = "https://www.google.com";

// Version is required, set to current timestamp.
byte[] version = Longs.toByteArray(System.currentTimeMillis());

// Using the SDK item builder class to create the document with
// appropriate attributes. This can be expanded to include metadata
// fields etc.
Item item = IndexingItemBuilder.fromConfiguration(documentId)
    .setItemType(IndexingItemBuilder.ItemType.CONTENT_ITEM)
    .setAcl(acl)
    .setSourceRepositoryUrl(IndexingItemBuilder.FieldOrValue.withValue(viewUrl))
    .setVersion(version)
    .build();

יצירת פריט שניתן להוסיף לאינדקס

אחרי שמגדירים את המטא-נתונים של הפריט, אפשר ליצור את הפריט בפועל שניתן להוסיף לאינדקס באמצעות RepositoryDoc.Builder. הדוגמה הבאה מראה איך ליצור פריט אחד שניתן להוסיף לאינדקס.

GraphTraversalSample.java
// For this sample, content is just plain text
String content = String.format("Hello world from sample doc %s", documentId);
ByteArrayContent byteContent = ByteArrayContent.fromString("text/plain", content);

RepositoryDoc.Builder docBuilder = new RepositoryDoc.Builder()
    .setItem(item)
    .setContent(byteContent, IndexingService.ContentFormat.TEXT);

RepositoryDoc הוא סוג של ApiOperation שמבצע את הבקשה בפועל של IndexingService.indexItem().

אפשר גם להשתמש בשיטה setRequestMode() מהמחלקה RepositoryDoc.Builder כדי לזהות את בקשת ההוספה לאינדקס בתור ASYNCHRONOUS או SYNCHRONOUS:

ASYNCHRONOUS
מצב אסינכרוני גורם לזמן אחזור ארוך יותר להוספה לאינדקס לשרת, ומכסה מכסת תפוקה גדולה לבקשות להוספה לאינדקס. מומלץ להשתמש במצב אסינכרוני לצורך הוספה ראשונית לאינדקס (מילוי חוסרים) של כל המאגר.
SYNCHRONOUS
מצב סינכרוני מאפשר זמן אחזור קצר יותר מהוספה לאינדקס לשרת, ומכסה מכסת תפוקה מוגבלת. מומלץ להשתמש במצב סינכרוני כדי להוסיף לאינדקס עדכונים ושינויים למאגר. אם לא צוין אחרת, ברירת המחדל של מצב הבקשה היא SYNCHRONOUS.

למקם את מזהי הצאצאים בתור ליצירת אינדקס ב-Cloud Search

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

GraphTraversalSample.java
// Queue the child nodes to visit after indexing this document
Set<String> childIds = getChildItemNames(documentId);
for (String id : childIds) {
  log.info(() -> String.format("Pushing child node %s", id));
  PushItem pushItem = new PushItem();
  docBuilder.addChildId(id, pushItem);
}

RepositoryDoc doc = docBuilder.build();

השלבים הבאים

אפשר לנסות את הפתרונות הבאים:

  • (אופציונלי) אפשר להשתמש בשיטה close() כדי לשחרר משאבים לפני ההשבתה.
  • (אופציונלי) יוצרים מחבר זהויות באמצעות ה-SDK של Identity Connector.

יצירה של מחבר תוכן באמצעות API ל-REST

בקטעים הבאים מוסבר איך ליצור מחבר תוכן באמצעות API ל-REST.

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

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

אסטרטגיית מעבר מלאה

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

אסטרטגיית המעבר הזו מתאימה למאגרים קטנים עם נתונים סטטיים בעיקר ולא היררכיים. כדאי להשתמש באסטרטגיית המעבר הזו גם כאשר זיהוי השינויים קשה או שאינו נתמך על ידי המאגר.

הצגת רשימה של אסטרטגיית מעבר

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

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

מעבר בתרשים

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

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

ישמו את אסטרטגיית המעבר ואת הפריטים באינדקס

כל רכיב ב-Cloud Search שאפשר להוסיף לאינדקס נקרא פריט ב-Cloud Search API. פריט יכול להיות קובץ, תיקייה, שורה בקובץ CSV או רשומה במסד נתונים.

לאחר רישום הסכימה, ניתן לאכלס את האינדקס על ידי:

  1. (אופציונלי) שימוש ב-items.upload כדי להעלות קבצים שגודלם עולה על 100KiB להוספה לאינדקס. לקבצים קטנים יותר, מומלץ להטמיע את התוכן כ-inlineContent באמצעות items.index.

  2. (אופציונלי) שימוש ב-media.upload כדי להעלות קובצי מדיה להוספה לאינדקס.

  3. שימוש ב-items.index כדי להוסיף את הפריט לאינדקס. לדוגמה, אם הסכימה משתמשת בהגדרת האובייקט בסכימת הסרט, בקשת הוספה לאינדקס של פריט אחד תיראה כך:

    {
      "name": "datasource/<data_source_id>/items/titanic",
      "acl": {
        "readers": [
          {
            "gsuitePrincipal": {
              "gsuiteDomain": true
            }
          }
        ]
      },
      "metadata": {
        "title": "Titanic",
        "viewUrl": "http://www.imdb.com/title/tt2234155/?ref_=nv_sr_1",
        "objectType": "movie"
      },
      "structuredData": {
        "object": {
          "properties": [
            {
              "name": "movieTitle",
              "textValues": {
                "values": [
                  "Titanic"
                ]
              }
            },
            {
              "name": "releaseDate",
              "dateValues": {
                "values": [
                  {
                    "year": 1997,
                    "month": 12,
                    "day": 19
                  }
                ]
              }
            },
            {
              "name": "actorName",
              "textValues": {
                "values": [
                  "Leonardo DiCaprio",
                  "Kate Winslet",
                  "Billy Zane"
                ]
              }
            },
            {
              "name": "genre",
              "enumValues": {
                "values": [
                  "Drama",
                  "Action"
                ]
              }
            },
            {
              "name": "userRating",
              "integerValues": {
                "values": [
                  8
                ]
              }
            },
            {
              "name": "mpaaRating",
              "textValues": {
                "values": [
                  "PG-13"
                ]
              }
            },
            {
              "name": "duration",
              "textValues": {
                "values": [
                  "3 h 14 min"
                ]
              }
            }
          ]
        }
      },
      "content": {
        "inlineContent": "A seventeen-year-old aristocrat falls in love with a kind but poor artist aboard the luxurious, ill-fated R.M.S. Titanic.",
        "contentFormat": "TEXT"
      },
      "version": "01",
      "itemType": "CONTENT_ITEM"
    }
    
  4. (אופציונלי) שימוש בקריאות items.get כדי לאמת שפריט נוסף לאינדקס.

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

טיפול בשינויים במאגר

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

במקום להשתמש בקריאות לאינדקס כדי להוסיף מאגר שלם לאינדקס מדי פעם, אפשר גם להשתמש בתור של Google Cloud לאינדקס כמנגנון למעקב אחרי שינויים ולהוסיף לאינדקס רק את הפריטים שהשתנו. אפשר להשתמש בבקשות items.push כדי להעביר פריטים לתור להצבעה ולעדכון מאוחר יותר. למידע נוסף על התור של ההוספה לאינדקס ב-Google Cloud, קראו את התור של Google Cloud ליצירת אינדקס.

מידע נוסף על Google Cloud Search API זמין במאמר Cloud Search API.