Bağlayıcıyı dağıtma

Cloud Search eğiticisinin bu sayfasında, veri kaynağının nasıl oluşturulacağı gösterilmektedir ve içerik bağlayıcısı içerir. Bu eğiticinin başından başlamak için Cloud Search başlangıç eğitimi

Bağlayıcı oluşturma

Çalışma dizininizi cloud-search-samples/end-to-end/connector olarak değiştirin dizinimize ekleyin ve şu komutu çalıştırın:

mvn package -DskipTests

Bu komut, kodu derler.

Hizmet hesabı kimlik bilgileri oluşturma

Bağlayıcının Cloud Search'ü çağırması için hizmet hesabı kimlik bilgileri gerekir API'ler. Kimlik bilgilerini oluşturmak için:

  1. Şuraya dön: Google Cloud konsolunuza giriş yapın.
  2. Soldaki gezinme panelinde Credentials'ı (Kimlik bilgileri) tıklayın. "Credential" (Kimlik Bilgisi) görünür.
  3. + KİMLİK BİLGİLERİ OLUŞTUR açılır listesini tıklayın ve Hizmet hesabı. "Hizmet hesabı oluştur" görünür.
  4. Hizmet hesabı adı alanına "tutorial" yazın.
  5. Hizmet hesabı kimliği değerini not edin (Hizmet hesabı adından hemen sonra). Bu değer daha sonra kullanılır.
  6. OLUŞTUR'u tıklayın. "Hizmet hesabı izinleri (isteğe bağlı)" iletişim kutusu görüntülenir.
  7. DEVAM'ı tıklayın. "Kullanıcıların bu hizmet hesabına erişmesine izin ver (isteğe bağlı)" iletişim kutusu görüntülenir.
  8. BİTTİ'yi tıklayın. "Credentials" (Kimlik Bilgileri) görünür.
  9. Hizmet Hesapları bölümünde, hizmet hesabı e-posta adresini tıklayın. "Hizmet hesap ayrıntıları" yardımcı olabilir.
  10. Anahtarlar'ın altında, ANAHTAR EKLE açılır listesini tıklayın ve Yeni anahtar oluşturun. "Özel anahtar oluştur" iletişim kutusu görüntülenir.
  11. OLUŞTUR'u tıklayın.
  12. (isteğe bağlı) "Şurada indirme işlemlerine izin vermek istiyor musunuz?: console.cloud.google.com?" iletişim kutusu göründüğünde İzin ver'i tıklayın.
  13. Özel anahtar dosyası bilgisayarınıza kaydedilir. Konumu not edin indirilmiş dosyadır. Bu dosya, içerik bağlayıcısını yapılandırarak Google Cloud Search API'lerini çağırırken kendi kimliğini doğrulayabilir.

Üçüncü taraf desteğini başlatma

Başka bir Cloud Search API'sini çağırabilmek için önce üçüncü tarafı başlatmanız gerekir desteği sona erecektir.

Cloud Search için üçüncü taraf desteğini başlatmak için:

  1. Cloud Search platform projenizde hizmet hesabı kimlik bilgileri bulunuyor. Ancak üçüncü taraf desteğini başlatmak için öncelikle uygulama kimlik bilgileridir. Web uygulaması oluşturmayla ilgili talimatlar için daha fazla bilgi için Kimlik bilgileri oluşturun. Bu adımı tamamladıktan sonra, bir istemci kimliği ve istemci gizli anahtarı dosyanız olmalıdır.

  2. Tekliflerinizi otomatikleştirmek ve optimize etmek için Google'ın OAuth 2 deneme alanı aşağıdaki adımları izleyin:

    1. Ayarlar'ı tıklayın ve Kendi kimlik doğrulama bilgilerinizi kullanın seçeneğini işaretleyin.
    2. 1. adımdaki istemci kimliğini ve istemci gizli anahtarını girin.
    3. Kapat'ı tıklayın.
    4. Kapsamlar alanına https://www.googleapis.com/auth/cloud_search.settings yazın. ve Yetkilendir'i tıklayın. OAuth 2 oyun alanı bir yetkilendirme kodu döndürür.
    5. Jetonlar için yetkilendirme kodu değiş tokuşu yap seçeneğini tıklayın Bir jeton döndürülür.
  3. Cloud Search için üçüncü taraf desteğini başlatmak için aşağıdaki curl'ü kullanın komutunu kullanın. [YOUR_ACCESS_TOKEN] yerine, elde ettiğiniz jetonla değiştirin. 2. adım.

    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
    

    Başarılı olursa yanıt gövdesi, operation öğesinin bir örneğini içerir. Örneğin:

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

    Başarısız olursa Cloud Search destek ekibiyle iletişime geçin.

  4. Bunu doğrulamak için operations.get işlemini kullanın üçüncü taraf desteği başlatıldığında:

    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
    

    Üçüncü taraf başlatma işlemi tamamlandığında, done alanı true olarak ayarlandı. Örneğin:

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

Veri kaynağını oluşturma

Ardından, Yönetici Konsolu'nda bir veri kaynağı oluşturun. Veri kaynağı etiketi, bağlayıcıyı kullanarak içeriğin dizine eklenmesi için bir ad alanı sağlar.

  1. Google Yönetici konsolunu açın.
  2. Uygulamalar simgesini tıklayın. "Uygulama yönetimi" görünür.
  3. Google Workspace'i tıklayın. "Uygulamalar Google Workspace yönetimi" görünür.
  4. Aşağı kaydırın ve Cloud Search'ü tıklayın. "Google Workspace ayarları" sayfa görünür.
  5. Üçüncü taraf veri kaynakları'nı tıklayın. "Veri Kaynakları" görünür.
  6. Yuvarlak sarı + işaretini tıklayın. "Yeni veri kaynağı ekle" iletişim kutusu görüntülenir.
  7. Görünen ad alanına "eğitim" yazın.
  8. Hizmet hesabı e-posta adresleri alanına önceki bölümde oluşturduğunuz hizmet hesabı. hizmet hesabının e-posta adresini değil, "the" hizmet hesapları sayfasını ziyaret edin.
  9. EKLE'yi tıklayın. "Veri kaynağı başarıyla oluşturuldu" iletişim kutusu görüntülenir.
  10. *Tamam'ı tıklayın. Yeni oluşturulan veri kaynağının kaynak kimliğini not edin. İlgili içeriği oluşturmak için kullanılan Kaynak kimliği, içerik bağlayıcısını yapılandırmak için kullanılır.

GitHub API için kişisel erişim jetonu oluşturun

Bağlayıcının doğru çalışabilmesi için GitHub API'ye sahip olmanız gerekir. Basitlik açısından, bağlayıcı, kişiselleştirilmiş erişim jetonlarıdır. Kişisel jetonlar, kimlik doğrulaması için OAuth'a benzer şekilde, sınırlı izin grubuna sahip bir kullanıcı.

  1. GitHub'a giriş yapın.
  2. Sağ üst köşedeki profil resminizi tıklayın. Açılır menü görünür.
  3. Ayarlar'ı tıklayın.
  4. Geliştirici ayarları'nı tıklayın.
  5. Kişisel erişim jetonları'nı tıklayın.
  6. Generate Personal access token (Kişisel erişim jetonu oluştur) seçeneğini tıklayın.
  7. Not alanına "Cloud Search tutorial" yazın.
  8. public_repo kapsamını kontrol edin.
  9. Generate token (Jeton oluştur) seçeneğini tıklayın.
  10. Oluşturulan jetonu not edin. Bağlayıcı tarafından GitHub'ı çağırmak için kullanılır API'ler içinde yer alır ve dizine ekleme işlemini gerçekleştirmek için API kotası sağlar.

Bağlayıcıyı yapılandırma

Kimlik bilgilerini ve veri kaynağını oluşturduktan sonra bağlayıcıyı güncelleyin bu değerleri dahil edecek şekilde yapılandırmalısınız:

  1. Komut satırında dizini şu şekilde değiştirin: cloud-search-samples/end-to-end/connector/
  2. sample-config.properties dosyasını bir metin düzenleyicide açın.
  3. api.serviceAccountPrivateKeyFile parametresini hizmet kimlik bilgileri ekleyin.
  4. api.sourceId parametresini, yüklediğiniz veri kaynağının kimliğine ayarlayın oluşturabilirsiniz.
  5. github.user parametresini GitHub kullanıcı adınıza ayarlayın.
  6. github.token parametresini, daha önce oluşturduğunuz erişim jetonuna ayarlayın.
  7. Dosyayı kaydedin.

Şemayı güncelleme

Bağlayıcı hem yapılandırılmış hem de yapılandırılmamış içeriği dizine ekler. Dizine eklemeden önce veri kaynağı şemasını güncellemeniz gerekir. Aşağıdaki komutu çalıştırın şemayı güncellemek için:

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

Bağlayıcıyı çalıştırma

Bağlayıcıyı çalıştırıp dizine eklemeye başlamak için şu komutu çalıştırın:

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

Bağlayıcı için varsayılan yapılandırma, tek bir depoyu dizine eklemektir googleworkspace kuruluşunda. Deponun dizine eklenmesi yaklaşık 1 dakika sürer. İlk dizine ekleme işleminden sonra, bağlayıcı yansıtılması gereken bir kod deposudur.

Kodu inceleme

Geri kalan bölümlerde bağlayıcının nasıl oluşturulduğu incelenmektedir.

Uygulama başlatılıyor

Bağlayıcının giriş noktası GithubConnector sınıfıdır. İlgili içeriği oluşturmak için kullanılan main yöntemi, SDK'nın IndexingApplication yöntemini örneklendirir ve başlatıyor.

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 tarafından sağlanan SDK, bir geçiş stratejisi uyguluyor. Cloud Search sıralarından yararlanarak için de kullanılabilir. GithubRepository adlı kullanıcıya yetki verir .

GitHub depolarında gezinme

Tam geçişler sırasında getIds(), yöntemi çağrılır.

Bağlayıcı, birden fazla depoyu veya kuruluşu dizine ekleyebilir. tek seferde bir GitHub deposuna geçilir. Kontrol noktası geçişinin şu listeyi içeren sonuçlarıyla döndürülür: getIds() için yapılan sonraki çağrılarda dizine eklenecek. Hata devam ettirilirse dizine ekleme işlemi, başlatılmak yerine mevcut depoda devam ettirilir. ele alacağız.

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() yöntemi, tek bir GitHub deposu. Bu yöntem, ApiOperations koleksiyonunu döndürür. temsil eder. Öğeler, kaynak adı ve öğenin mevcut durumunu temsil eden bir karma değeri.

Karma değeri, GitHub'ın sonraki geçişlerinde kullanılır ekleyebilirsiniz. Bu değer, içeriğin uygun olup olmadığını belirlemek için hafif bir kontrol sağlar ek içerik yüklemeye gerek kalmadan değişti. Konnektör gizlice tüm öğeleri sıraya alır. Öğe yeniyse veya hash değeri değişmişse sırada yoklama için kullanılabilir. Aksi takdirde, öğe değiştirilmemiş olarak kabul edilir.

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;
}

Sıra işleniyor

Tam geçiş tamamlandıktan sonra, bağlayıcı, sıralanması gereken öğelerdir. getDoc() yöntemi çağrılır. Yöntem şunları okur: GitHub'dan öğe çıkar ve bunu uygun gösterime dönüştürür emin olmanız gerekir.

Bağlayıcı, herhangi bir zamanda değiştirilebilecek canlı verilerle çalışırken getDoc(), sıradaki öğenin hâlâ geçerli olduğunu da doğrular. ve artık mevcut olmayan tüm öğeleri dizinden siler.

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));
  }
}

Bağlayıcı dizinlerinin her bir GitHub nesnesi için indexItem() yöntemi, öğe temsilini oluşturma işlemini Cloud Search. Örneğin, içerik öğelerinin temsilini oluşturmak için:

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();
}

Ardından, arama arayüzünü dağıtın.

Önceki Sonraki