Menelusuri dokumen

Sebelum memulai

Untuk memproses dokumen contoh ke Document AI Warehouse, lihat Panduan Memulai Cepat.

Saat menentukan skema dokumen dan membuat dokumen, penting untuk mempertimbangkan properti yang ingin Anda tentukan dan cara penggunaannya dengan penelusuran, jika ada.

Tandai properti yang dapat difilter jika Anda ingin menggunakan properti tersebut untuk menyertakan atau mengecualikan sebagian dokumen untuk penelusuran. Misalnya, Anda dapat membuat properti yang merepresentasikan "Vendor" yang dapat difilter karena pengguna ingin menelusuri invoice dari vendor tertentu.

Jika Anda ingin membuat histogram (lihat contohnya di bagian selanjutnya dalam topik ini) pada properti, properti tersebut harus dapat difilter.

Tandai properti yang dapat ditelusuri jika properti tersebut memiliki data yang ingin dikueri pengguna selama penelusuran kata kunci.

Penelusuran teks lengkap adalah proses pengambilan semua dokumen yang cocok dengan kata kunci penelusuran dalam teksnya yang dapat ditelusuri. Pengguna memberikan daftar kata kunci (kata-kata yang dipisahkan oleh spasi), yang mungkin diketik ke dalam kolom penelusuran di UI. Di Document AI Warehouse, kata kunci diproses dan dikonversi menjadi kueri yang tepat. Pemrosesan tersebut menghilangkan kata henti ("the", "in", dan "an") serta melakukan stemming pada kata-kata yang tersisa. Stemming mengurangi kata menjadi versi umum dari kata-kata, sehingga variasi kata cocok. Misalnya: "kerja", "bekerja", "telah bekerja".

Data apa yang ditelusuri?

  • plain_text dokumen.
  • Jika Anda mengimpor objek Document AI, gunakan cloud_ai_document.text yang disematkan.
  • Nama tampilan dokumen.
  • Semua properti yang dapat ditelusuri.

Kueri sebagian mendukung sintaksis gaya AIP Google. Secara khusus, kueri mendukung literal, operator logika, operator negasi, operator perbandingan, dan fungsi.

  • Literal: Nilai literal kosong (contoh: "42", "Hugo") adalah nilai yang akan dicocokkan. Penelusuran dilakukan pada teks lengkap dokumen dan properti yang dapat ditelusuri.
  • Operator logika: "AND", "and", "OR", dan "or" adalah operator logika biner (contoh: "engineer OR developer").
  • Operator negasi: "NOT" dan "!" adalah operator negasi (contoh: "NOT software").
  • Operator perbandingan: mendukung operator perbandingan biner =, !=, <, >, <=, dan >= untuk string, numerik, enum, boolean. Juga mendukung operator like ~~ untuk string. Fitur ini menyediakan fungsi penelusuran semantik dengan mengurai, melakukan stemming, dan memperluas sinonim terhadap kueri input.

    Untuk menentukan properti dalam kueri, ekspresi sisi kiri dalam perbandingan harus berupa ID properti termasuk induk. Sisi kanan harus berupa literal. Misalnya: \"projects/123/locations/us\".property_a < 1 cocok dengan hasil yang property_a-nya kurang dari 1 di project 123 dan lokasi us. Literal dan ekspresi perbandingan dapat dihubungkan dalam satu kueri (contoh: software engineer \"projects/123/locations/us\".salary > 100).

  • Fungsi: fungsi yang didukung adalah LOWER([property_name]) untuk melakukan pencocokan yang tidak peka huruf besar/kecil dan EMPTY([property_name]) untuk memfilter keberadaan kunci.

  • Mendukung ekspresi bertingkat yang terhubung menggunakan tanda kurung dan operator logika. Operator logika default adalah AND jika tidak ada operator di antara ekspresi.

Kueri dapat digunakan dengan filter lain, misalnya time_filters dan folder_name_filter. Operator ini terhubung dengan operator AND di balik layar.

Kueri penelusuran dapat difilter berdasarkan parameter tambahan seperti property, time, schema, folder, dan creator.

Panggilan ke permintaan penelusuran

Untuk memanggil layanan penelusuran, Anda harus menggunakan permintaan penelusuran, yang ditentukan sebagai berikut:

{
  "requestMetadata": {
    object (RequestMetadata)
  },
  "documentQuery": {
    object (DocumentQuery)
  },
  "offset": integer,
  "pageSize": integer,
  "pageToken": string,
  "orderBy": string,
  "histogramQueries": [
    {
      object (HistogramQuery)
    }
  ],
  "requireTotalSize": boolean,
  "totalResultSize": enum (TotalResultSize),
  "qaSizeLimit": integer
}

Kolom parent harus diisi dengan format:

/projects/PROJECT_ID/locations/LOCATION

Respons terhadap permintaan penelusuran

Respons penelusuran didefinisikan sebagai berikut:

{
  "matchingDocuments": [
    {
      object (MatchingDocument)
    }
  ],
  "nextPageToken": string,
  "totalSize": integer,
  "metadata": {
    object (ResponseMetadata)
  },
  "histogramQueryResults": [
    {
      object (HistogramQueryResult)
    }
  ]
}

Kueri Dokumen

Kolom document_query didefinisikan sebagai berikut:

{
  "query": string,
  "isNlQuery": boolean,
  "customPropertyFilter": string,
  "timeFilters": [
    {
      object (TimeFilter)
    }
  ],
  "documentSchemaNames": [
    string
  ],
  "propertyFilter": [
    {
      object (PropertyFilter)
    }
  ],
  "fileTypeFilter": {
    object (FileTypeFilter)
  },
  "folderNameFilter": string,
  "queryContext": [
    string
  ],
  "documentCreatorFilter": [
    string
  ],
  "customWeightsMetadata": {
    object (CustomWeightsMetadata)
  }
}

Kolom query adalah untuk kata-kata kueri penelusuran pengguna yang meminta. Biasanya, kueri ini berasal dari kolom penelusuran di UI.

Filter

Document AI Warehouse menawarkan berbagai filter.

Filter waktu dokumen

Filter waktu pembuatan dan pembaruan berfungsi seperti yang Anda harapkan: menemukan dokumen yang cocok dengan kata kunci dalam jangka waktu tertentu.

Objek TimeFilter digunakan untuk menentukan rentang waktu dan didefinisikan sebagai berikut:

{
  "timeRange": {
    object (Interval)
  },
  "timeField": enum (TimeField)
}

Di kolom time_field, Anda menentukan apakah rentang waktu yang ditentukan di time_range adalah untuk waktu pembuatan dokumen atau waktu pembaruan terakhir dokumen.

Kolom time_range menentukan rentang waktu sebagai Interval. Interval didefinisikan sebagai:

{
  "startTime": string,
  "endTime": string
}

Filter kreator

Untuk menelusuri dokumen yang dibuat oleh pengguna tertentu, gunakan filter pembuat. Contoh:

  {
    document_query {
      query: "videogames director",
      documentCreatorFilter: [
        "diane@some_company.com",
        "frank@some_company.com",
      ],
    },
  }

Filter properti

Filter properti memungkinkan Anda menentukan filter pada properti yang telah Anda tentukan dalam skema, selama properti tersebut telah dikonfigurasi agar dapat difilter.

Misalnya, menggunakan filter properti di industri hukum dapat memfilter properti yang disebut COURT untuk menelusuri hanya dokumen dari pengadilan tertentu.

Filter properti menggunakan objek PropertyFilter. Anda dapat memiliki lebih dari satu filter properti. Saat Anda menggunakan beberapa filter properti, filter tersebut digabungkan menggunakan operator OR. Filter properti ditentukan sebagai berikut:

  {
    "documentSchemaName": string,
    "condition": string
  }

Properti ditentukan dalam skema. Dengan demikian, kolom documentSchemaName adalah tempat Anda menentukan skema untuk properti yang Anda gunakan untuk pemfilteran. Di kolom condition, Anda menentukan logika yang diinginkan. Untuk contoh penggunaan kolom documentSchemaName dan condition, lihat contoh sebelumnya di halaman ini.

Dokumen yang cocok

Dokumen yang cocok berisi Document dan cuplikan (dibahas nanti). Dokumen yang ditampilkan di MatchingDocument bukan dokumen yang terisi lengkap. Objek ini berisi data minimal untuk menampilkan daftar hasil penelusuran kepada pengguna yang meminta. Jika dokumen lengkap diinginkan (misalnya, jika pengguna mengklik hasil penelusuran), maka dokumen lengkap harus diambil melalui GetDocument API.

Kolom Document berikut diisi: Project number, Document id, Document schema id, Create time, Update time, Display name, Raw document file type, Reference id, dan Filterable properties.

Dokumen yang cocok akan terlihat seperti ini:

{
  "document": {
    object (Document)
  },
  "searchTextSnippet": string,
  "qaResult": {
    object (QAResult)
  }
}

Peringkat/pengurutan

Permintaan penelusuran memungkinkan Anda menentukan cara pengurutan hasil yang diinginkan. Untuk mengurutkan, gunakan kolom order_by dalam permintaan penelusuran. Nilai yang mungkin untuk kolom ini mencakup:

  • relevance desc - relevansi menurun, yaitu kecocokan terbaik berada di paling atas.
  • upload_date desc - tanggal dokumen dibuat dalam urutan menurun (terbaru di atas).
  • upload_date - tanggal dokumen dibuat dalam urutan menaik (paling lama di atas).
  • update_date desc - tanggal dokumen terakhir diperbarui dalam urutan menurun (yang terbaru di atas).
  • Update_date - tanggal dokumen terakhir diperbarui dalam urutan menaik (yang paling lama di atas).

Jika Anda tidak menentukan pengurutan, tetapi memberikan kata kunci penelusuran, pengurutan akan dilakukan berdasarkan relevansi menurun (kecocokan terbaik di atas). Jika pengurutan maupun kata kunci tidak diberikan, pengurutan default adalah menurut waktu pembaruan secara menurun (dokumen terbaru di atas).

Penomoran halaman

Penomoran halaman berguna untuk menampilkan data satu halaman kepada pengguna akhir. Di sini, Anda dapat menentukan ukuran halaman dan mendapatkan jumlah total ukuran hasil untuk ditampilkan kembali kepada pengguna (misalnya, "Menampilkan 50 dokumen dari 300").

Tetapkan kolom page_size ke jumlah hasil yang diinginkan yang ingin Anda terima dengan permintaan penelusuran. Hal ini mungkin sesuai dengan persyaratan ukuran tampilan hasil penelusuran UI.

Ada dua mekanisme: offset dan token halaman.

Offset adalah indeks ke dalam daftar dokumen yang dapat ditampilkan yang ingin Anda tampilkan. Misalnya, offset 5 berarti Anda menginginkan dokumen keenam dan seterusnya. Mungkin Anda akan menambah offset dengan ukuran halaman untuk hasil halaman berikutnya.

Atau, Anda dapat menggunakan token halaman dan tidak perlu khawatir tentang penghitungan offset berikutnya. Setelah membuat permintaan penelusuran pertama, Anda akan mendapatkan respons penelusuran yang berisi kolom next_page_token. Jika kolom ini kosong, berarti tidak ada lagi hasil. Jika kolom tidak kosong, gunakan token ini dalam permintaan penelusuran berikutnya dengan menyetel kolom page_token.

Beberapa UI menampilkan jumlah dokumen yang ditemukan oleh penelusuran. Misalnya, you are viewing 10 documents of 120. Untuk mendapatkan jumlah dokumen yang ditampilkan, tetapkan kolom require_total_size boolean permintaan ke True. Tips: require_total_size=True akan mengurangi performa. Tetapkan ini pada kueri halaman pertama, lalu tetapkan ini ke false pada semua permintaan berikutnya, dengan menyimpan total jumlah dalam variabel lokal.

Contoh Kode

Python

Untuk mengetahui informasi selengkapnya, lihat dokumentasi referensi API Python Document AI Warehouse.

Untuk melakukan autentikasi ke Document AI Warehouse, siapkan Kredensial Default Aplikasi. Untuk mengetahui informasi selengkapnya, lihat Menyiapkan autentikasi untuk lingkungan pengembangan lokal.


from google.cloud import contentwarehouse

# TODO(developer): Uncomment these variables before running the sample.
# project_number = 'YOUR_PROJECT_NUMBER'
# location = 'YOUR_PROJECT_LOCATION' # Format is 'us' or 'eu'
# document_query_text = 'YOUR_DOCUMENT_QUERY'
# user_id = 'user:YOUR_SERVICE_ACCOUNT_ID' # Format is "user:xxxx@example.com"


def search_documents_sample(
    project_number: str, location: str, document_query_text: str, user_id: str
) -> None:
    # Create a client
    client = contentwarehouse.DocumentServiceClient()

    # The full resource name of the location, e.g.:
    # projects/{project_number}/locations/{location}
    parent = client.common_location_path(project=project_number, location=location)

    # File Type Filter
    # Options: DOCUMENT, FOLDER
    file_type_filter = contentwarehouse.FileTypeFilter(
        file_type=contentwarehouse.FileTypeFilter.FileType.DOCUMENT
    )

    # Document Text Query
    document_query = contentwarehouse.DocumentQuery(
        query=document_query_text,
        file_type_filter=file_type_filter,
    )

    # Histogram Query
    histogram_query = contentwarehouse.HistogramQuery(
        histogram_query='count("DocumentSchemaId")'
    )

    request_metadata = contentwarehouse.RequestMetadata(
        user_info=contentwarehouse.UserInfo(id=user_id)
    )

    # Define request
    request = contentwarehouse.SearchDocumentsRequest(
        parent=parent,
        request_metadata=request_metadata,
        document_query=document_query,
        histogram_queries=[histogram_query],
    )

    # Make the request
    response = client.search_documents(request=request)

    # Print search results
    for matching_document in response.matching_documents:
        document = matching_document.document
        # Display name - schema display name.
        # Name.
        # Create date.
        # Snippet - keywords are highlighted with <b> & </b>.
        print(
            f"{document.display_name} - {document.document_schema_name}\n"
            f"{document.name}\n"
            f"{document.create_time}\n"
            f"{matching_document.search_text_snippet}\n"
        )

    # Print histogram
    for histogram_query_result in response.histogram_query_results:
        print(
            f"Histogram Query: {histogram_query_result.histogram_query}\n"
            f"| {'Schema':<70} | {'Count':<15} |"
        )
        for key, value in histogram_query_result.histogram.items():
            print(f"| {key:<70} | {value:<15} |")

Java

Untuk mengetahui informasi selengkapnya, lihat dokumentasi referensi API Java Document AI Warehouse.

Untuk melakukan autentikasi ke Document AI Warehouse, siapkan Kredensial Default Aplikasi. Untuk mengetahui informasi selengkapnya, lihat Menyiapkan autentikasi untuk lingkungan pengembangan lokal.

import com.google.cloud.contentwarehouse.v1.DocumentQuery;
import com.google.cloud.contentwarehouse.v1.DocumentServiceClient;
import com.google.cloud.contentwarehouse.v1.DocumentServiceClient.SearchDocumentsPagedResponse;
import com.google.cloud.contentwarehouse.v1.DocumentServiceSettings;
import com.google.cloud.contentwarehouse.v1.FileTypeFilter;
import com.google.cloud.contentwarehouse.v1.FileTypeFilter.FileType;
import com.google.cloud.contentwarehouse.v1.LocationName;
import com.google.cloud.contentwarehouse.v1.RequestMetadata;
import com.google.cloud.contentwarehouse.v1.SearchDocumentsRequest;
import com.google.cloud.contentwarehouse.v1.SearchDocumentsResponse.MatchingDocument;
import com.google.cloud.contentwarehouse.v1.UserInfo;
import com.google.cloud.resourcemanager.v3.Project;
import com.google.cloud.resourcemanager.v3.ProjectName;
import com.google.cloud.resourcemanager.v3.ProjectsClient;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

public class SearchDocuments {
  public static void main(String[] args) throws IOException, 
        InterruptedException, ExecutionException, TimeoutException { 
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String location = "your-region"; // Format is "us" or "eu".
    String documentQuery = "your-document-query";
    String userId = "your-user-id"; // Format is user:<user-id>

    searchDocuments(projectId, location, documentQuery, userId);
  }

  // Searches all documents for a given Document Query
  public static void searchDocuments(String projectId, String location,
        String documentQuery, String userId) throws IOException, InterruptedException,
          ExecutionException, TimeoutException { 
    String projectNumber = getProjectNumber(projectId);

    String endpoint = "contentwarehouse.googleapis.com:443";
    if (!"us".equals(location)) {
      endpoint = String.format("%s-%s", location, endpoint);
    }

    DocumentServiceSettings documentServiceSettings = 
             DocumentServiceSettings.newBuilder().setEndpoint(endpoint)
             .build(); 

    /*
     * Create the Document Service Client 
     * Initialize client that will be used to send requests. 
     * This client only needs to be created once, and can be reused for multiple requests. 
     */
    try (DocumentServiceClient documentServiceClient = 
            DocumentServiceClient.create(documentServiceSettings)) {  

      /*
       * The full resource name of the location, e.g.:
       * projects/{project_number}/locations/{location} 
       */
      String parent = LocationName.format(projectNumber, location);

      // Define RequestMetadata object for context of the user making the API call
      RequestMetadata requestMetadata = RequestMetadata.newBuilder()
          .setUserInfo(
          UserInfo.newBuilder()
            .setId(userId)
            .build())
            .build();

      // Set file type for filter to 'DOCUMENT'
      FileType documentFileType = FileType.DOCUMENT;

      // Create a file type filter for documents 
      FileTypeFilter fileTypeFilter = FileTypeFilter.newBuilder()
          .setFileType(documentFileType)
          .build();

      // Create document query to search all documents for text given at input
      DocumentQuery query = DocumentQuery.newBuilder()
          .setQuery(documentQuery)
          .setFileTypeFilter(fileTypeFilter)
          .build();

      /*
       * Create the request to search all documents for specified query. 
       * Please note the offset in this request is to only return the specified number of results 
       * to avoid hitting the API quota. 
       */
      SearchDocumentsRequest searchDocumentsRequest = SearchDocumentsRequest.newBuilder()
          .setParent(parent)
          .setRequestMetadata(requestMetadata)
          .setOffset(5)
          .setDocumentQuery(query)
          .build();

      // Make the call to search documents with document service client and store the response
      SearchDocumentsPagedResponse searchDocumentsPagedResponse = 
          documentServiceClient.searchDocuments(searchDocumentsRequest);

      // Iterate through response and print search results for documents matching the search query
      for (MatchingDocument matchingDocument :
          searchDocumentsPagedResponse.iterateAll()) {
        System.out.println(
            "Display Name: " + matchingDocument.getDocument().getDisplayName()
            + "Document Name: " + matchingDocument.getDocument().getName()
            + "Document Creation Time: " + matchingDocument.getDocument().getCreateTime().toString()
            + "Search Text Snippet: " + matchingDocument.getSearchTextSnippet());
      }
    }
  }

  private static String getProjectNumber(String projectId) throws IOException { 
    /*
     * Initialize client that will be used to send requests. 
     * This client only needs to be created once, and can be reused for multiple requests.
     */
    try (ProjectsClient projectsClient = ProjectsClient.create()) { 
      ProjectName projectName = ProjectName.of(projectId); 
      Project project = projectsClient.getProject(projectName);
      String projectNumber = project.getName(); // Format returned is projects/xxxxxx
      return projectNumber.substring(projectNumber.lastIndexOf("/") + 1);
    } 
  }
}

Langkah berikutnya