ทําให้เครื่องมือเชื่อมต่อใช้งานได้

หน้านี้ของบทแนะนำ Cloud Search แสดงวิธีตั้งค่าแหล่งข้อมูล และเครื่องมือเชื่อมต่อเนื้อหาสำหรับการจัดทำดัชนีข้อมูล หากต้องการเริ่มต้นตั้งแต่ต้นของบทแนะนำนี้ โปรดดูบทแนะนำการเริ่มต้นใช้งาน Cloud Search

สร้างเครื่องมือเชื่อมต่อ

เปลี่ยนไดเรกทอรีที่ใช้งานอยู่เป็นไดเรกทอรี cloud-search-samples/end-to-end/connector แล้วเรียกใช้คำสั่งนี้

mvn package -DskipTests

คำสั่งนี้จะดาวน์โหลดการอ้างอิงที่จำเป็นสำหรับการสร้าง ตัวเชื่อมต่อเนื้อหาและคอมไพล์โค้ด

สร้างข้อมูลเข้าสู่ระบบบัญชีบริการ

ตัวเชื่อมต่อต้องใช้ข้อมูลเข้าสู่ระบบของบัญชีบริการเพื่อเรียกใช้ Cloud Search API วิธีสร้างข้อมูลเข้าสู่ระบบ

  1. กลับไปที่คอนโซล Google Cloud
  2. คลิกข้อมูลเข้าสู่ระบบที่การนำทางด้านซ้าย หน้า "ข้อมูลเข้าสู่ระบบ" จะปรากฏขึ้น
  3. คลิกรายการแบบเลื่อนลง + สร้างข้อมูลเข้าสู่ระบบ แล้วเลือก บัญชีบริการ หน้า "สร้างบัญชีบริการ" จะปรากฏขึ้น
  4. ป้อน "tutorial" ในช่องชื่อบัญชีบริการ
  5. จดค่ารหัสบัญชีบริการ (ต่อจากชื่อบัญชีบริการ) ระบบจะใช้ค่านี้ในภายหลัง
  6. คลิกสร้าง กล่องโต้ตอบ "สิทธิ์ของบัญชีบริการ (ไม่บังคับ)" จะปรากฏขึ้น
  7. คลิกดำเนินการต่อ กล่องโต้ตอบ "ให้สิทธิ์ผู้ใช้เข้าถึงบัญชีบริการนี้ (ไม่บังคับ)" จะปรากฏขึ้น
  8. คลิกเสร็จ หน้าจอ "ข้อมูลเข้าสู่ระบบ" จะปรากฏขึ้น
  9. คลิกอีเมลบัญชีบริการในส่วนบัญชีบริการ หน้า "รายละเอียดบัญชีบริการ" จะปรากฏขึ้น
  10. ในส่วนคีย์ ให้คลิกรายการแบบเลื่อนลงเพิ่มคีย์ แล้วเลือก สร้างคีย์ใหม่ กล่องโต้ตอบ "สร้างคีย์ส่วนตัว" จะปรากฏขึ้น
  11. คลิกสร้าง
  12. (ไม่บังคับ) หากกล่องโต้ตอบ "คุณต้องการอนุญาตให้ดาวน์โหลดใน console.cloud.google.com ไหม" ปรากฏขึ้น ให้คลิกอนุญาต
  13. ระบบจะบันทึกไฟล์คีย์ส่วนตัวลงในคอมพิวเตอร์ จดตำแหน่ง ของไฟล์ที่ดาวน์โหลด ระบบจะใช้ไฟล์นี้เพื่อกำหนดค่าเครื่องมือเชื่อมต่อเนื้อหาเพื่อให้ เครื่องมือดังกล่าวตรวจสอบสิทธิ์ของตัวเองได้เมื่อเรียกใช้ Google Cloud Search API

เริ่มต้นการสนับสนุนจากบุคคลที่สาม

คุณต้องเริ่มต้นการรองรับบุคคลที่สามสำหรับ Google Cloud Search ก่อนจึงจะเรียกใช้ Cloud Search API อื่นๆ ได้

วิธีเริ่มต้นการรองรับบุคคลที่สามสำหรับ Cloud Search

  1. โปรเจ็กต์แพลตฟอร์ม Cloud Search มีข้อมูลเข้าสู่ระบบบัญชีบริการ อย่างไรก็ตาม คุณต้องสร้างข้อมูลเข้าสู่ระบบของเว็บแอปพลิเคชันเพื่อเริ่มต้นการสนับสนุนบุคคลที่สาม ดูวิธีการสร้างข้อมูลเข้าสู่ระบบของเว็บแอปพลิเคชันได้ที่สร้างข้อมูลเข้าสู่ระบบ เมื่อทำขั้นตอนนี้เสร็จแล้ว คุณควรมีไฟล์รหัสไคลเอ็นต์และรหัสลับไคลเอ็นต์

  2. ใช้ OAuth 2 Playground ของ Google เพื่อรับโทเค็นเพื่อการเข้าถึง

    1. คลิกการตั้งค่า แล้วเลือกใช้ข้อมูลเข้าสู่ระบบการตรวจสอบสิทธิ์ของคุณเอง
    2. ป้อนรหัสไคลเอ็นต์และรหัสลับไคลเอ็นต์จากขั้นตอนที่ 1
    3. คลิกปิด
    4. ในช่องขอบเขต ให้พิมพ์ https://www.googleapis.com/auth/cloud_search.settings แล้วคลิกให้สิทธิ์ OAuth 2 Playground จะแสดงรหัสการให้สิทธิ์
    5. คลิกเปลี่ยนรหัสการให้สิทธิ์ของโทเค็น ระบบจะแสดงโทเค็น
  3. หากต้องการเริ่มต้นการรองรับบุคคลที่สามสำหรับ Cloud Search ให้ใช้คำสั่ง curl ต่อไปนี้ อย่าลืมแทนที่ [YOUR_ACCESS_TOKEN] ด้วยโทเค็นที่ได้รับใน ขั้นตอนที่ 2

    curl --request POST \
    'https://cloudsearch.googleapis.com/v1:initializeCustomer' \
      --header 'Authorization: Bearer [YOUR_ACCESS_TOKEN]' \
      --header 'Accept: application/json' \
      --header 'Content-Type: application/json' \
      --data '{}' \
      --compressed
    

    หากทำสำเร็จ เนื้อหาการตอบกลับจะมีอินสแตนซ์ของ operation เช่น

    {
    name: "operations/customers/01b3fqdm/lro/AOIL6eBv7fEfiZ_hUSpm8KQDt1Mnd6dj5Ru3MXf-jri4xK6Pyb2-Lwfn8vQKg74pgxlxjrY"
    }
    

    หากไม่สำเร็จ โปรดติดต่อทีมสนับสนุนของ Cloud Search

  4. ใช้ operations.get เพื่อยืนยันว่าได้เริ่มต้นการสนับสนุนจากบุคคลที่สามแล้ว

    curl \
    'https://cloudsearch.googleapis.com/v1/operations/customers/01b3fqdm/lro/AOIL6eBv7fEfiZ_hUSpm8KQDt1Mnd6dj5Ru3MXf-jri4xK6Pyb2-Lwfn8vQKg74pgxlxjrY?key=
    [YOUR_API_KEY]' \
    --header 'Authorization: Bearer [YOUR_ACCESS_TOKEN]' \
    --header 'Accept: application/json' \
    --compressed
    

    เมื่อการเริ่มต้นของบุคคลที่สามเสร็จสมบูรณ์แล้ว จะมีฟิลด์ done ตั้งค่าเป็น true เช่น

    {
    name: "operations/customers/01b3fqdm/lro/AOIL6eBv7fEfiZ_hUSpm8KQDt1Mnd6dj5Ru3MXf-jri4xK6Pyb2-Lwfn8vQKg74pgxlxjrY"
    done: true
    }
    

สร้างแหล่งข้อมูล

จากนั้นสร้างแหล่งข้อมูลในคอนโซลผู้ดูแลระบบ แหล่งข้อมูล มีเนมสเปซสำหรับการจัดทำดัชนีเนื้อหาโดยใช้ตัวเชื่อมต่อ

  1. เปิดคอนโซลผู้ดูแลระบบของ Google
  2. คลิกไอคอนแอป หน้า "การดูแลระบบแอป" จะปรากฏขึ้น
  3. คลิก Google Workspace หน้า "การดูแลระบบแอป Google Workspace" จะปรากฏขึ้น
  4. เลื่อนลงแล้วคลิก Cloud Search หน้า "การตั้งค่าสำหรับ Google Workspace" จะปรากฏขึ้น
  5. คลิกแหล่งข้อมูลของบุคคลที่สาม หน้า "แหล่งข้อมูล" จะปรากฏขึ้น
  6. คลิก + สีเหลืองทรงกลม กล่องโต้ตอบ "เพิ่มแหล่งข้อมูลใหม่" จะปรากฏขึ้น
  7. ในช่องชื่อที่แสดง ให้พิมพ์ "บทแนะนำ"
  8. ในช่องอีเมลบัญชีบริการ ให้ป้อนอีเมลของบัญชีบริการที่คุณสร้างขึ้นในส่วนก่อนหน้า หากไม่ทราบ อีเมลของบัญชีบริการ ให้ค้นหาค่าใน หน้าบัญชีบริการ
  9. คลิกเพิ่ม กล่องโต้ตอบ "สร้างแหล่งข้อมูลเรียบร้อยแล้ว" จะปรากฏขึ้น
  10. คลิก *ตกลง จดรหัสแหล่งที่มาของแหล่งข้อมูลที่สร้างขึ้นใหม่ ระบบจะใช้รหัสแหล่งข้อมูลเพื่อกำหนดค่าโปรแกรมเชื่อมต่อเนื้อหา

สร้างโทเค็นเพื่อการเข้าถึงส่วนบุคคลสำหรับ GitHub API

ตัวเชื่อมต่อต้องมีการเข้าถึงที่ได้รับการตรวจสอบสิทธิ์ไปยัง GitHub API เพื่อให้มีโควต้าเพียงพอ เพื่อความสะดวก ตัวเชื่อมต่อจะใช้ประโยชน์จากโทเค็นเพื่อการเข้าถึงส่วนบุคคลแทน OAuth โทเค็นส่วนบุคคลช่วยให้ตรวจสอบสิทธิ์ในฐานะ ผู้ใช้ที่มีชุดสิทธิ์แบบจำกัดคล้ายกับ OAuth

  1. เข้าสู่ระบบ GitHub
  2. คลิกรูปโปรไฟล์ที่มุมขวาบน เมนูแบบเลื่อนลงจะปรากฏขึ้น
  3. คลิกการตั้งค่า
  4. คลิกการตั้งค่าสำหรับนักพัฒนาซอฟต์แวร์
  5. คลิกโทเค็นเพื่อการเข้าถึงส่วนบุคคล
  6. คลิกสร้างโทเค็นเพื่อการเข้าถึงส่วนบุคคล
  7. ป้อน "บทแนะนำ Cloud Search" ในช่องหมายเหตุ
  8. ตรวจสอบขอบเขต public_repo
  9. คลิกสร้างโทเค็น
  10. จดโทเค็นที่สร้างขึ้น ตัวเชื่อมต่อใช้โทเค็นนี้เพื่อเรียกใช้ API ของ GitHub และให้โควต้า API เพื่อทำการจัดทำดัชนี

กำหนดค่าเครื่องมือเชื่อมต่อ

หลังจากสร้างข้อมูลเข้าสู่ระบบและแหล่งข้อมูลแล้ว ให้อัปเดตการกำหนดค่าตัวเชื่อมต่อ ให้มีค่าต่อไปนี้

  1. จากบรรทัดคำสั่ง ให้เปลี่ยนไดเรกทอรีเป็น cloud-search-samples/end-to-end/connector/
  2. เปิดไฟล์ sample-config.properties ด้วยเครื่องมือแก้ไขข้อความ
  3. ตั้งค่าพารามิเตอร์ api.serviceAccountPrivateKeyFile เป็นเส้นทางไฟล์ของ ข้อมูลเข้าสู่ระบบบริการที่คุณดาวน์โหลดไว้ก่อนหน้านี้
  4. ตั้งค่าพารามิเตอร์ api.sourceId เป็นรหัสของแหล่งข้อมูลที่คุณ สร้างไว้ก่อนหน้านี้
  5. ตั้งค่าพารามิเตอร์ github.user เป็นชื่อผู้ใช้ GitHub ของคุณ
  6. ตั้งค่าพารามิเตอร์ github.token เป็นโทเค็นเพื่อการเข้าถึงที่คุณสร้างไว้ก่อนหน้านี้
  7. บันทึกไฟล์

อัปเดตสคีมา

ตัวเชื่อมต่อจะจัดทำดัชนีทั้งเนื้อหาที่มีโครงสร้างและไม่มีโครงสร้าง ก่อนจัดทำดัชนี ข้อมูล คุณต้องอัปเดตสคีมาสำหรับแหล่งข้อมูล เรียกใช้คำสั่งต่อไปนี้ เพื่ออัปเดตสคีมา

mvn exec:java -Dexec.mainClass=com.google.cloudsearch.tutorial.SchemaTool \
    -Dexec.args="-Dconfig=sample-config.properties"

เรียกใช้เครื่องมือเชื่อมต่อ

หากต้องการเรียกใช้ตัวเชื่อมต่อและเริ่มจัดทำดัชนี ให้เรียกใช้คำสั่งต่อไปนี้

mvn exec:java -Dexec.mainClass=com.google.cloudsearch.tutorial.GithubConnector \
    -Dexec.args="-Dconfig=sample-config.properties"

การกำหนดค่าเริ่มต้นสำหรับเครื่องมือเชื่อมต่อคือการจัดทำดัชนีที่เก็บเดียว ในองค์กร googleworkspace การจัดทำดัชนีที่เก็บข้อมูลจะใช้เวลาประมาณ 1 นาที หลังจากการจัดทำดัชนีครั้งแรก ตัวเชื่อมต่อจะสำรวจการเปลี่ยนแปลงใน ที่เก็บที่ต้องแสดงในดัชนี Cloud Search ต่อไป

ตรวจสอบโค้ด

ส่วนที่เหลือจะพิจารณาว่าตัวเชื่อมต่อสร้างขึ้นมาอย่างไร

การเริ่มต้นแอปพลิเคชัน

จุดแรกเข้าของตัวเชื่อมต่อคือคลาส GithubConnector เมธอด main จะสร้างอินสแตนซ์ของ IndexingApplication ของ SDK และเริ่มทำงาน

GithubConnector.java
/**
 * Main entry point for the connector. Creates and starts an indexing
 * application using the {@code ListingConnector} template and the sample's
 * custom {@code Repository} implementation.
 *
 * @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 GithubRepository();
  IndexingConnector connector = new ListingConnector(repository);
  IndexingApplication application = new IndexingApplication.Builder(connector, args)
      .build();
  application.start();
}

ListingConnector ที่ SDK จัดเตรียมให้จะใช้กลยุทธ์การข้าม ที่ใช้ประโยชน์จากคิวของ Cloud Search เพื่อติดตามสถานะของรายการในดัชนี โดยจะมอบสิทธิ์ให้ GithubRepository ซึ่งใช้โดยตัวเชื่อมต่อตัวอย่าง เพื่อเข้าถึงเนื้อหาจาก GitHub

การไปยังที่เก็บ GitHub

ในระหว่างการข้ามผ่านแบบเต็ม ระบบจะเรียกใช้เมธอด getIds() เพื่อพุชรายการที่อาจต้องจัดทำดัชนีลงในคิว

โดยตัวเชื่อมต่อจะจัดทำดัชนีที่เก็บหรือองค์กรหลายแห่งได้ ระบบจะสำรวจที่เก็บ GitHub ทีละรายการเพื่อลด ผลกระทบจากความล้มเหลว ระบบจะแสดงจุดตรวจสอบพร้อมผลลัพธ์ของการข้ามที่มีรายการ ที่เก็บที่จะจัดทำดัชนีในการเรียกใช้ getIds() ครั้งต่อๆ ไป หากเกิดข้อผิดพลาด ระบบจะทำการจัดทำดัชนีต่อที่ที่เก็บปัจจุบันแทนที่จะเริ่ม ตั้งแต่ต้น

GithubRepository.java
/**
 * Gets all of the existing item IDs from the data repository. While
 * multiple repositories are supported, only one repository is traversed
 * per call. The remaining repositories are saved in the checkpoint
 * are traversed on subsequent calls. This minimizes the amount of
 * data that needs to be reindex in the event of an error.
 *
 * <p>This method is called by {@link ListingConnector#traverse()} during
 * <em>full traversals</em>. Every document ID and metadata hash value in
 * the <em>repository</em> is pushed to the Cloud Search queue. Each pushed
 * document is later polled and processed in the {@link #getDoc(Item)} method.
 * <p>
 * The metadata hash values are pushed to aid document change detection. The
 * queue sets the document status depending on the hash comparison. If the
 * pushed ID doesn't yet exist in Cloud Search, the document's status is
 * set to <em>new</em>. If the ID exists but has a mismatched hash value,
 * its status is set to <em>modified</em>. If the ID exists and matches
 * the hash value, its status is unchanged.
 *
 * <p>In every case, the pushed content hash value is only used for
 * comparison. The hash value is only set in the queue during an
 * update (see {@link #getDoc(Item)}).
 *
 * @param checkpoint value defined and maintained by this connector
 * @return this is typically a {@link PushItems} instance
 */
@Override
public CheckpointCloseableIterable<ApiOperation> getIds(byte[] checkpoint)
    throws RepositoryException {
  List<String> repositories;
  // Decode the checkpoint if present to get the list of remaining
  // repositories to index.
  if (checkpoint != null) {
    try {
      FullTraversalCheckpoint decodedCheckpoint = FullTraversalCheckpoint
          .fromBytes(checkpoint);
      repositories = decodedCheckpoint.getRemainingRepositories();
    } catch (IOException e) {
      throw new RepositoryException.Builder()
          .setErrorMessage("Unable to deserialize checkpoint")
          .setCause(e)
          .build();
    }
  } else {
    // No previous checkpoint, scan for repositories to index
    // based on the connector configuration.
    try {
      repositories = scanRepositories();
    } catch (IOException e) {
      throw toRepositoryError(e, Optional.of("Unable to scan repositories"));
    }
  }

  if (repositories.isEmpty()) {
    // Nothing left to index. Reset the checkpoint to null so the
    // next full traversal starts from the beginning
    Collection<ApiOperation> empty = Collections.emptyList();
    return new CheckpointCloseableIterableImpl.Builder<>(empty)
        .setCheckpoint((byte[]) null)
        .setHasMore(false)
        .build();
  }

  // Still have more repositories to index. Pop the next repository to
  // index off the list. The remaining repositories make up the next
  // checkpoint.
  String repositoryToIndex = repositories.get(0);
  repositories = repositories.subList(1, repositories.size());

  try {
    log.info(() -> String.format("Traversing repository %s", repositoryToIndex));
    Collection<ApiOperation> items = collectRepositoryItems(repositoryToIndex);
    FullTraversalCheckpoint newCheckpoint = new FullTraversalCheckpoint(repositories);
    return new CheckpointCloseableIterableImpl.Builder<>(items)
        .setHasMore(true)
        .setCheckpoint(newCheckpoint.toBytes())
        .build();
  } catch (IOException e) {
    String errorMessage = String.format("Unable to traverse repo: %s",
        repositoryToIndex);
    throw toRepositoryError(e, Optional.of(errorMessage));
  }
}

เมธอด collectRepositoryItems() จะจัดการการข้ามผ่านของที่เก็บ GitHub เดียว เมธอดนี้จะแสดงผลคอลเล็กชันของ ApiOperations ซึ่งแสดงถึงรายการที่จะพุชลงในคิว ระบบจะพุชรายการเป็น ชื่อทรัพยากรและค่าแฮชที่แสดงสถานะปัจจุบันของรายการ

ระบบจะใช้ค่าแฮชในการข้ามผ่านที่เก็บ GitHub ในครั้งต่อๆ ไป ค่านี้จะช่วยให้ตรวจสอบได้ง่ายว่าเนื้อหามีการเปลี่ยนแปลงหรือไม่โดยไม่ต้องอัปโหลดเนื้อหาเพิ่มเติม ตัวเชื่อมต่อจะจัดคิวรายการทั้งหมดโดยไม่เลือก หากรายการเป็นรายการใหม่หรือค่าแฮชมีการเปลี่ยนแปลง ระบบจะทำให้รายการพร้อมสำหรับการสำรวจในคิว มิฉะนั้นจะถือว่าสินค้าไม่มีการแก้ไข

GithubRepository.java
/**
 * Fetch IDs to  push in to the queue for all items in the repository.
 * Currently captures issues & content in the master branch.
 *
 * @param name Name of repository to index
 * @return Items to push into the queue for later indexing
 * @throws IOException if error reading issues
 */
private Collection<ApiOperation> collectRepositoryItems(String name)
    throws IOException {
  List<ApiOperation> operations = new ArrayList<>();
  GHRepository repo = github.getRepository(name);

  // Add the repository as an item to be indexed
  String metadataHash = repo.getUpdatedAt().toString();
  String resourceName = repo.getHtmlUrl().getPath();
  PushItem repositoryPushItem = new PushItem()
      .setMetadataHash(metadataHash);
  PushItems items = new PushItems.Builder()
      .addPushItem(resourceName, repositoryPushItem)
      .build();

  operations.add(items);
  // Add issues/pull requests & files
  operations.add(collectIssues(repo));
  operations.add(collectContent(repo));
  return operations;
}

การประมวลผลคิว

หลังจากที่การข้ามทั้งหมดเสร็จสมบูรณ์แล้ว ตัวเชื่อมต่อจะเริ่มสำรวจคิวเพื่อหาข้อมูลที่ต้องจัดทำดัชนี ระบบจะเรียกใช้เมธอด getDoc() สำหรับแต่ละรายการที่ดึงมาจากคิว เมธอดนี้จะอ่าน รายการจาก GitHub และแปลงเป็นรูปแบบที่เหมาะสม สำหรับการจัดทำดัชนี

เนื่องจากเครื่องมือเชื่อมต่อทำงานกับข้อมูลสดที่อาจมีการเปลี่ยนแปลงได้ทุกเมื่อ getDoc() จึงตรวจสอบด้วยว่ารายการในคิวยังคงใช้งานได้และลบรายการที่ไม่มีอยู่ออกจากดัชนี

GithubRepository.java
/**
 * Gets a single data repository item and indexes it if required.
 *
 * <p>This method is called by the {@link ListingConnector} during a poll
 * of the Cloud Search queue. Each queued item is processed
 * individually depending on its state in the data repository.
 *
 * @param item the data repository item to retrieve
 * @return the item's state determines which type of
 * {@link ApiOperation} is returned:
 * {@link RepositoryDoc}, {@link DeleteItem}, or {@link PushItem}
 */
@Override
public ApiOperation getDoc(Item item) throws RepositoryException {
  log.info(() -> String.format("Processing item: %s ", item.getName()));
  Object githubObject;
  try {
    // Retrieve the item from GitHub
    githubObject = getGithubObject(item.getName());
    if (githubObject instanceof GHRepository) {
      return indexItem((GHRepository) githubObject, item);
    } else if (githubObject instanceof GHPullRequest) {
      return indexItem((GHPullRequest) githubObject, item);
    } else if (githubObject instanceof GHIssue) {
      return indexItem((GHIssue) githubObject, item);
    } else if (githubObject instanceof GHContent) {
      return indexItem((GHContent) githubObject, item);
    } else {
      String errorMessage = String.format("Unexpected item received: %s",
          item.getName());
      throw new RepositoryException.Builder()
          .setErrorMessage(errorMessage)
          .setErrorType(RepositoryException.ErrorType.UNKNOWN)
          .build();
    }
  } catch (FileNotFoundException e) {
    log.info(() -> String.format("Deleting item: %s ", item.getName()));
    return ApiOperations.deleteItem(item.getName());
  } catch (IOException e) {
    String errorMessage = String.format("Unable to retrieve item: %s",
        item.getName());
    throw toRepositoryError(e, Optional.of(errorMessage));
  }
}

สำหรับออบเจ็กต์ GitHub แต่ละรายการที่ตัวเชื่อมต่อจัดทำดัชนี เมธอดที่เกี่ยวข้อง indexItem()จะจัดการการสร้างการแสดงรายการสำหรับ Cloud Search เช่น หากต้องการสร้างการแสดงเนื้อหารายการต่างๆ ให้ทำดังนี้

GithubRepository.java
/**
 * Build the ApiOperation to index a content item (file).
 *
 * @param content      Content item to index
 * @param previousItem Previous item state in the index
 * @return ApiOperation (RepositoryDoc if indexing,  PushItem if not modified)
 * @throws IOException if unable to create operation
 */
private ApiOperation indexItem(GHContent content, Item previousItem)
    throws IOException {
  String metadataHash = content.getSha();

  // If previously indexed and unchanged, just requeue as unmodified
  if (canSkipIndexing(previousItem, metadataHash)) {
    return notModified(previousItem.getName());
  }

  String resourceName = new URL(content.getHtmlUrl()).getPath();
  FieldOrValue<String> title = FieldOrValue.withValue(content.getName());
  FieldOrValue<String> url = FieldOrValue.withValue(content.getHtmlUrl());

  String containerName = content.getOwner().getHtmlUrl().getPath();
  String programmingLanguage = FileExtensions.getLanguageForFile(content.getName());

  // Structured data based on the schema
  Multimap<String, Object> structuredData = ArrayListMultimap.create();
  structuredData.put("organization", content.getOwner().getOwnerName());
  structuredData.put("repository", content.getOwner().getName());
  structuredData.put("path", content.getPath());
  structuredData.put("language", programmingLanguage);

  Item item = IndexingItemBuilder.fromConfiguration(resourceName)
      .setTitle(title)
      .setContainerName(containerName)
      .setSourceRepositoryUrl(url)
      .setItemType(IndexingItemBuilder.ItemType.CONTAINER_ITEM)
      .setObjectType("file")
      .setValues(structuredData)
      .setVersion(Longs.toByteArray(System.currentTimeMillis()))
      .setHash(content.getSha())
      .build();

  // Index the file content too
  String mimeType = FileTypeMap.getDefaultFileTypeMap()
      .getContentType(content.getName());
  AbstractInputStreamContent fileContent = new InputStreamContent(
      mimeType, content.read())
      .setLength(content.getSize())
      .setCloseInputStream(true);
  return new RepositoryDoc.Builder()
      .setItem(item)
      .setContent(fileContent, IndexingService.ContentFormat.RAW)
      .setRequestMode(IndexingService.RequestMode.SYNCHRONOUS)
      .build();
}

จากนั้นให้ติดตั้งใช้งานอินเทอร์เฟซการค้นหา

ก่อนหน้า ถัดไป