In Dokumenten suchen

Vorbereitung

Informationen zum Aufnehmen von Beispieldokumenten in Document AI Warehouse finden Sie in der Kurzanleitung.

Wenn Sie Ihre Dokumentschemas definieren und Ihre Dokumente erstellen, ist es wichtig, zu überlegen, welche Eigenschaften Sie definieren möchten und wie sie für die Suche verwendet werden sollen.

Markieren Sie eine Property als filterbar, wenn Sie sie verwenden möchten, um einen Teil der Dokumente für eine Suche ein- oder auszuschließen. Sie können beispielsweise eine Eigenschaft, die einen „Anbieter“-Filter darstellt, filterbar machen, weil Ihre Nutzer nach Rechnungen von einem bestimmten Anbieter suchen möchten.

Wenn Sie ein Histogramm für eine Property erstellen möchten (siehe das Beispiel weiter unten), muss die Property filterbar sein.

Markieren Sie eine Property als durchsuchbar, wenn sie Daten enthält, die Ihre Nutzer bei einer Keyword-Suche abfragen möchten.

Bei der Volltextsuche werden alle Dokumente abgerufen, die mit den Suchbegriffen in ihrem durchsuchbaren Text übereinstimmen. Der Nutzer gibt eine Liste von Keywords an (Wörter, die durch ein Leerzeichen getrennt sind), die vermutlich in ein Suchfeld auf der Benutzeroberfläche eingegeben wurden. In Document AI Warehouse werden die Keywords verarbeitet und in eine geeignete Abfrage umgewandelt. Bei dieser Verarbeitung werden Stoppwörter („the“, „in“ und „an“) entfernt und die verbleibenden Wörter werden auf ihren Wortstamm reduziert. Beim Stemming wird das Wort auf eine gemeinsame Version der Formulierung reduziert, sodass Wortvariationen übereinstimmen. Beispiele: „Arbeit“, „arbeiten“, „gearbeitet“.

Welche Daten werden durchsucht?

  • Die plain_text des Dokuments.
  • Wenn Sie ein Document AI-Objekt importieren, verwenden Sie die eingebettete cloud_ai_document.text.
  • Der display_name des Dokuments.
  • Alle durchsuchbaren Attribute.

Die Abfrage unterstützt teilweise die Google AIP-Stilsyntax. Die Abfrage unterstützt Literale, logische Operatoren, Negationsoperatoren, Vergleichsoperatoren und Funktionen.

  • Literale: Ein einfacher Literalwert (z. B. „42“, „Hugo“) ist ein Wert, der abgeglichen werden soll. Es wird im gesamten Text des Dokuments und in den durchsuchbaren Eigenschaften gesucht.
  • Logische Operatoren: „AND“, „and“, „OR“ und „or“ sind binäre logische Operatoren (Beispiel: „engineer OR developer“).
  • Negationsoperatoren: „NOT“ und „!“ sind Negationsoperatoren (Beispiel: „NOT software“).
  • Vergleichsoperatoren: Die binären Vergleichsoperatoren =, !=, <, >, <= und >= werden für String-, numerische, Enum- und boolesche Werte unterstützt. Unterstützung des LIKE-Operators ~~ für Strings. Es bietet eine semantische Suchfunktion, indem die Eingabeanfrage geparst, auf den Wortstamm reduziert und um Synonyme erweitert wird.

    Wenn Sie eine Property in der Abfrage angeben möchten, muss der Ausdruck auf der linken Seite des Vergleichs die Property-ID einschließlich des übergeordneten Elements sein. Die rechte Seite muss Literale enthalten. Beispiel: \"projects/123/locations/us\".property_a < 1 stimmt mit Ergebnissen überein, deren property_a im Projekt 123 und am Standort us kleiner als 1 ist. Die Literale und der Vergleichsausdruck können in einer einzelnen Abfrage verbunden werden (Beispiel: software engineer \"projects/123/locations/us\".salary > 100).

  • Funktionen: Unterstützte Funktionen sind LOWER([property_name]), um eine Übereinstimmung mit Groß-/Kleinschreibung durchzuführen, und EMPTY([property_name]), um nach dem Vorhandensein eines Schlüssels zu filtern.

  • Unterstützung von verschachtelten Ausdrücken, die mit Klammern und logischen Operatoren verbunden sind. Der Standardoperator ist AND, wenn zwischen Ausdrücken keine Operatoren vorhanden sind.

Die Abfrage kann mit anderen Filtern wie time_filters und folder_name_filter verwendet werden. Sie sind mit dem Operator AND verbunden.

Suchanfragen können nach zusätzlichen Parametern wie property, time, schema, folder und creator gefiltert werden.

Aufruf einer Suchanfrage

Um den Suchdienst aufzurufen, müssen Sie eine Suchanfrage verwenden, die so definiert ist:

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

Das Feld parent muss im folgenden Format ausgefüllt werden:

/projects/PROJECT_ID/locations/LOCATION

Antwort auf eine Suchanfrage

Die Suchantwort wird so definiert:

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

Dokumentabfrage

Das Feld document_query ist so definiert:

{
  "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)
  }
}

Das Feld „query“ ist für die Suchanfragewörter des anfragenden Nutzers vorgesehen. Normalerweise stammen sie aus dem Suchfeld in der Benutzeroberfläche.

Filter

Document AI Warehouse bietet eine Vielzahl von Filtern.

Zeitfilter für Dokumente

Der Zeitfilter zum Erstellen und Aktualisieren funktioniert wie erwartet: Er findet Dokumente, die den Suchbegriffen innerhalb eines bestimmten Zeitraums entsprechen.

Mit einem TimeFilter-Objekt wird der Zeitraum angegeben. Es ist so definiert:

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

Im Feld time_field geben Sie an, ob sich der im Feld time_range angegebene Zeitraum auf die Erstellungszeit oder die letzte Aktualisierungszeit des Dokuments bezieht.

Im Feld time_range wird der Zeitraum als Interval angegeben. Ein Interval wird so definiert:

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

Creator-Filter

Wenn Sie nach Dokumenten suchen möchten, die von einem bestimmten Nutzer oder mehreren Nutzern erstellt wurden, verwenden Sie den Filter „Ersteller“. Beispiel:

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

Property-Filter

Mit dem Attributfilter können Sie Filter für alle Attribute angeben, die Sie in einem Schema definiert haben, sofern das Attribut als filterbar konfiguriert wurde.

Wenn Sie beispielsweise in der Rechtsbranche Property-Filter verwenden, können Sie nach einer Property namens COURT filtern, um nur Dokumente eines bestimmten Gerichts zu durchsuchen.

Für Property-Filter wird ein PropertyFilter-Objekt verwendet. Sie können mehrere Attributfilter haben. Wenn Sie mehrere Attributfilter verwenden, werden sie mit dem Operator OR kombiniert. Ein Attributfilter wird so definiert:

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

Eigenschaften werden in Schemas definiert. Im Feld documentSchemaName geben Sie also das Schema für das Attribut an, das Sie zum Filtern verwenden. Im Feld condition geben Sie die gewünschte Logik an. Beispiele für die Verwendung der Felder documentSchemaName und condition finden Sie in den vorherigen Beispielen auf dieser Seite.

 – vollständige Referenz

Übereinstimmendes Dokument

Ein übereinstimmendes Dokument enthält ein Document und einen Snippet (siehe unten). Das zurückgegebene Dokument in MatchingDocument ist nicht vollständig ausgefüllt. Sie enthält nur die Daten, die zum Anzeigen einer Suchergebnisliste für den anfragenden Nutzer erforderlich sind. Wenn das vollständige Dokument benötigt wird (z. B. wenn der Nutzer auf ein Suchergebnis geklickt hat), sollte es über die GetDocument API abgerufen werden.

Die folgenden Document-Felder sind ausgefüllt: Project number, Document id, Document schema id, Create time, Update time, Display name, Raw document file type, Reference id und Filterable properties.

Ein entsprechendes Dokument würde so aussehen:

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

Ranking/Sortierung

Im Suchantrag können Sie angeben, wie die Ergebnisse sortiert werden sollen. Zum Sortieren verwenden Sie das Feld order_by in der Suchanfrage. Mögliche Werte für dieses Feld:

  • relevance desc – absteigende Relevanz, d. h. die besten Übereinstimmungen werden oben angezeigt.
  • upload_date desc – das Datum, an dem das Dokument erstellt wurde, in absteigender Reihenfolge (neueste oben).
  • upload_date – das Datum, an dem das Dokument erstellt wurde, in aufsteigender Reihenfolge (ältestes oben).
  • update_date desc: Das Datum, an dem das Dokument zuletzt aktualisiert wurde, in absteigender Reihenfolge (neuestes oben).
  • Update_date: Das Datum, an dem das Dokument zuletzt aktualisiert wurde, in aufsteigender Reihenfolge (ältestes oben).

Wenn Sie keine Sortierung angeben, aber Suchbegriffe angeben, wird nach absteigender Relevanz sortiert (die besten Übereinstimmungen oben). Wenn weder die Sortierung noch die Keywords angegeben sind, wird standardmäßig nach absteigender Aktualisierungszeit sortiert (die neuesten Dokumente oben).

Seitenumbruch

Die Paginierung ist nützlich, um dem Endnutzer eine Seite mit Daten anzuzeigen. Hier können Sie die Größe der Seite angeben und eine Gesamtzahl der Ergebnisgröße abrufen, die dem Nutzer angezeigt werden soll (z. B. „50 von 300 Dokumenten werden angezeigt“).

Legen Sie das Feld page_size auf die gewünschte Anzahl von Ergebnissen fest, die Sie mit der Suchanfrage erhalten möchten. Dies kann den Anforderungen an die Größe der Suchergebnisse auf der Benutzeroberfläche entsprechen.

Es gibt zwei Mechanismen: Offset und Seitentoken.

Ein Offset ist der Index in der Liste der zurückzugebenden Dokumente, die Sie zurückgeben möchten. Ein Offset von 5 bedeutet beispielsweise, dass Sie das sechste Dokument und alle nachfolgenden Dokumente abrufen möchten. Wahrscheinlich würden Sie den Offset für die nächste Ergebnisseite um die Seitengröße erhöhen.

Alternativ können Sie ein Seitentoken verwenden und müssen den nächsten Offset nicht berechnen. Nachdem Sie Ihre erste Suchanfrage gesendet haben, erhalten Sie eine Suchantwort, die das Feld next_page_token enthält. Wenn dieses Feld leer ist, gibt es keine weiteren Ergebnisse. Wenn das Feld nicht leer ist, verwenden Sie dieses Token in Ihrer nächsten Suchanfrage, indem Sie das Feld page_token festlegen.

In einigen Benutzeroberflächen wird die Anzahl der Dokumente angezeigt, die bei der Suche gefunden wurden. Beispiel: you are viewing 10 documents of 120. Wenn Sie eine Anzahl von Dokumenten zurückgeben möchten, setzen Sie das Feld require_total_size boolean der Anfrage auf True. Tipp: Für require_total_size=True wird die Leistung beeinträchtigt. Legen Sie diesen Wert in der ersten Seitenabfrage fest und dann in allen nachfolgenden Anfragen auf false. Bewahren Sie die Gesamtzahl in einer lokalen Variablen auf.

Codebeispiele

Python

Weitere Informationen finden Sie in der Referenzdokumentation zur Document AI Warehouse Python API.

Richten Sie zur Authentifizierung bei Document AI Warehouse die Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.


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

Weitere Informationen finden Sie in der Referenzdokumentation zur Document AI Warehouse Java API.

Richten Sie zur Authentifizierung bei Document AI Warehouse die Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.

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

Nächste Schritte