In Dokumenten suchen

Vorbereitung

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

Beim Definieren Ihrer Dokumentschemas und Erstellen Ihrer Dokumente ist es wichtig, zu überlegen, welche Attribute Sie definieren möchten und wie sie gegebenenfalls für die Suche verwendet werden.

Markieren Sie einen Attributfilter als filterbar, wenn Sie dieses Attribut verwenden möchten, um einen Teil der Dokumente für eine Suche ein- oder auszuschließen. Sie können beispielsweise ein Attribut, das einen „Anbieter“ darstellt, als filterbar festlegen, weil Ihre Nutzer nach Rechnungen eines bestimmten Anbieters suchen möchten.

Wenn Sie ein Histogramm für ein Attribut erstellen möchten (siehe das Beispiel weiter unten in diesem Thema), muss das Attribut filterbar sein.

Markieren Sie ein Attribut als durchsuchbar, wenn es Daten enthält, die Ihre Nutzer bei einer Keyword-Suche abfragen möchten.

Bei der Volltextsuche werden alle Dokumente abgerufen, die mit den Such-Keywords in ihrem durchsuchbaren Text übereinstimmen. Der Nutzer gibt eine Liste von Keywords an (Wörter, die durch ein Leerzeichen getrennt sind), die er vermutlich in ein Suchfeld in der Benutzeroberfläche eingegeben hat. In Document AI Warehouse werden die Keywords verarbeitet und in eine entsprechende Abfrage umgewandelt. Bei dieser Verarbeitung werden Stoppwörter („der“, „die“, „das“, „in“ und „ein“) entfernt und die verbleibenden Wörter werden auf ihre Stammform reduziert. Durch die Reduzierung auf die Stammform werden auch Wortvariationen gefunden. Beispiel: „arbeiten“, „arbeitet“, „arbeitete“.

Welche Daten werden durchsucht?

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

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

  • Literale: Ein reiner Literalwert (Beispiele: „42“, „Hugo“) ist ein Wert, mit dem abgeglichen werden soll. Es wird im gesamten Text des Dokuments und in den durchsuchbaren Attributen 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: unterstützen die binären Vergleichsoperatoren =, !=, <, >, <= und >= für String, numerisch, Enum und boolesch. Außerdem wird der Operator „like“ ~~ für String unterstützt. Die semantische Suche wird durch Parsen, Reduzieren auf die Stammform und Erweitern von Synonymen für die Eingabeabfrage ermöglicht.

    Wenn Sie ein Attribut in der Abfrage angeben möchten, muss der Ausdruck auf der linken Seite des Vergleichs die Attribut-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 einzigen Abfrage verbunden werden (Beispiel: software engineer \"projects/123/locations/us\".salary > 100).

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

  • Verschachtelte Ausdrücke, die mit Klammern und logischen Operatoren verbunden sind, werden unterstützt. Der Standardoperator ist AND, wenn zwischen den Ausdrücken keine Operatoren vorhanden sind.

Die Abfrage kann mit anderen Filtern verwendet werden, z.B. time_filters und folder_name_filter. Sie werden im Hintergrund 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 ist 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 enthält die Suchbegriffe des anfragenden Nutzers. In der Regel stammen diese aus dem Suchfeld in der Benutzeroberfläche.

Filter

Document AI Warehouse bietet eine Vielzahl von Filtern.

Zeitfilter für Dokumente

Der Zeitfilter für Erstellungs- und Aktualisierungszeit findet Dokumente, die die Keywords innerhalb eines bestimmten Zeitraums enthalten.

Ein TimeFilter-Objekt wird verwendet, um den Zeitraum anzugeben. Es ist so definiert:

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

Im Feld time_field geben Sie an, ob sich der in 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 ist so definiert:

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

Filter für Ersteller

Wenn Sie nach Dokumenten suchen möchten, die von bestimmten Nutzern erstellt wurden, verwenden Sie den Filter für Ersteller. Beispiel:

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

Attributfilter

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

In der Rechtsbranche können Sie beispielsweise mit Attributfiltern nach einem Attribut namens COURT filtern, um nur Dokumente eines bestimmten Gerichts zu suchen.

Attributfilter verwenden ein PropertyFilter-Objekt. Sie können mehrere Attributfilter verwenden. Wenn Sie mehrere Attributfilter verwenden, werden sie mit dem Operator OR kombiniert. Ein Attributfilter ist so definiert:

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

Attribute 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.

Übereinstimmendes Dokument

Ein übereinstimmendes Dokument enthält ein Document und ein Snippet (wird später erläutert). Das zurückgegebene Dokument in MatchingDocument ist kein vollständig ausgefülltes Dokument. Es enthält nur die Mindestdaten, die erforderlich sind, um dem anfragenden Nutzer eine Liste mit Suchergebnissen anzuzeigen. Wenn das vollständige Dokument gewünscht ist (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 übereinstimmendes Dokument sieht so aus:

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

Rangfolge/Sortierung

In der Suchanfrage können Sie angeben, wie die Ergebnisse sortiert werden sollen. Verwenden Sie dazu das Feld order_by in der Suchanfrage. Folgende Werte sind für dieses Feld möglich:

  • relevance desc : Relevanz absteigend, d. h. die besten Übereinstimmungen stehen oben.
  • 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 (älteste oben).
  • update_date desc : Das Datum, an dem das Dokument zuletzt aktualisiert wurde, in absteigender Reihenfolge (neueste oben).
  • Update_date : Das Datum, an dem das Dokument zuletzt aktualisiert wurde, in aufsteigender Reihenfolge (älteste oben).

Wenn Sie keine Sortierung angeben, aber Such-Keywords angeben, wird nach Relevanz absteigend sortiert (die besten Übereinstimmungen stehen oben). Wenn weder die Sortierung noch Keywords angegeben werden, wird standardmäßig nach Aktualisierungszeit absteigend sortiert (die neuesten Dokumente stehen oben).

Seitenumbruch

Die Paginierung ist nützlich, um dem Endnutzer eine Seite mit Daten anzuzeigen. Hier können Sie die Seitengröße angeben und eine Gesamtzahl der Ergebnisse 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 Anzeigegröße 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 möchten. Vermutlich würden Sie den Offset um die Seitengröße erhöhen, um die nächste Seite mit Ergebnissen zu erhalten.

Alternativ können Sie ein Seitentoken verwenden und müssen den nächsten Offset nicht berechnen. Nachdem Sie Ihre erste Suchanfrage gestellt 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.

Einige Benutzeroberflächen zeigen die Anzahl der Dokumente an, die bei der Suche gefunden wurden. Beispiel: you are viewing 10 documents of 120. Wenn Sie eine Anzahl der Dokumente zurückgeben möchten, legen Sie das Feld require_total_size boolean der Anfrage auf True fest. Tipp: require_total_size=True wirkt sich negativ auf die Leistung aus. Legen Sie dies für die erste Seitenabfrage fest und setzen Sie es dann für alle nachfolgenden Anfragen auf false. Behalten Sie die Gesamtzahl in einer lokalen Variablen bei.

Codebeispiele

Python

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

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 Document AI Warehouse Java API Referenzdokumentation.

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