Umgang mit Suchergebnissen

Wenn ein Abfrageaufruf normal abgeschlossen wird, erfolgt die Rückgabe des Ergebnisses in Form eines Results-Objekts. Das Ergebnisobjekt gibt an, wie viele übereinstimmende Dokumente im Index gefunden und wie viele davon zurückgegeben wurden. Außerdem enthält es eine Sammlung übereinstimmender ScoredDocuments. Die Sammlung enthält normalerweise einen Teil aller gefundenen übereinstimmenden Dokumente, da die Suche bei jedem Aufruf eine begrenzte Anzahl von Dokumenten zurückgibt. Mithilfe eines Offsets oder Cursors können Sie alle übereinstimmenden Dokumente abrufen, jeweils in Form einer Teilmenge.

Ergebnisse

// index and query have already been defined ...
try {
    Results<ScoredDocument> result = index.search(query);
    long totalMatches = result.getNumberFound();
    int numberOfDocsReturned = result.getNumberReturned();
    Collection<ScoredDocument> listOfDocs = result.getResults();
} catch (SearchException e) {
    // handle exception...
}

Je nach Wert der Abfrageoption limit kann die Anzahl der übereinstimmenden Dokumente, die im Ergebnis zurückgegeben werden, geringer als die gefundene Anzahl sein. Die gefundene Anzahl ist eine Schätzung, wenn die Genauigkeit für die gefundene Anzahl kleiner ist als die tatsächlich gefundene Anzahl. Unabhängig davon, wie Sie die Suchoptionen konfigurieren, liegt das Limit eines Aufrufs von search() bei 10.000 übereinstimmenden Dokumenten.

Wenn mehr Dokumente gefunden wurden, als zurückgegeben werden können, und Sie alle abrufen möchten, müssen Sie die Suche wiederholen. Dies kann mithilfe eines Offsets oder eines Cursors erfolgen, wie weiter unten erläutert.

Bewertete Dokumente

Die Suchergebnisse enthalten eine Sammlung von ScoredDocuments, die der Abfrage entsprechen. Sie können die Sammlung mit der Methode getResults() abrufen oder über ihre Elemente direkt aus den Suchergebnissen heraus iterieren. Beide Methoden werden hier gezeigt:

// index and query have already been defined ...
Results<ScoredDocument> result = index.search(query);

// Grab the collection for later use:
Collection<ScoredDocument> theDocs = result.getResults();

// Alternatively, iterate over the results directly:
for (ScoredDocument doc : result) {
    // do work
}

Standardmäßig enthält ein bewertetes Dokument alle Felder des Originaldokuments, das indexiert wurde. Wenn in den Abfrageoptionen setFieldsToReturn angegeben wurde, sind nur diese festgelegten Felder in den Ergebnissen enthalten, wenn Sie getFields() für das Dokument aufrufen. Falls Sie mit addExpressionToReturn oder setFieldsToSnippet berechnete Felder erstellt haben, rufen Sie diese separat ab. Dazu rufen Sie getExpressions() für das Dokument auf.

Offsets verwenden

Wenn Ihre Suche mehr Dokumente findet, als gleichzeitig zurückgegeben werden können, verwenden Sie einen Offset-Wert, um in der Liste der übereinstimmenden Dokumente zu indexieren. Nehmen wir als Beispiel das Standardabfragelimit von 20 Dokumenten. Nachdem Sie die Suche zum ersten Mal (mit einem Offset-Wert von 0) ausgeführt und die ersten 20 Dokumente abgerufen haben, rufen Sie die nächsten 20 Dokumente mit derselben Suche, aber diesmal mit einem Offset-Wert von 20 ab. Wiederholen Sie die Suche und erhöhen Sie den Offset-Wert jedes Mal um die Anzahl der zurückgegebenen Dokumente:

// index and queryString have already been defined

try {
    int numberRetrieved = 0;
    int offset = 0;
    do {
        // build options and query
        QueryOptions options = QueryOptions.newBuilder()
            .setOffset(offset)
            .build();
        Query query = Query.newBuilder().setOptions(options).build(queryString);

        // search at least once
        Results<ScoredDocument> result = index.search(query);
        numberRetrieved = result.getNumberReturned();
        if (numberRetrieved > 0) {
            offset += numberRetrieved;
            // process the matched docs
        }

    }
    while (numberRetrieved > 0);
} catch (SearchException e) {
    // handle exception...
}

Wenn Sie über eine sehr große Ergebnismenge iterieren, können Offsets ineffizient sein.

Cursors verwenden

Sie können auch Cursors verwenden, um eine Teilmenge der Ergebnisse abzurufen. Cursors sind hilfreich, wenn Sie Ihre Suchergebnisse auf aufeinanderfolgenden Seiten darstellen und gewährleisten möchten, dass keine Dokumente übersprungen werden, falls ein Index zwischen Abfragen geändert wurde. Cursors sind auch effizienter, wenn Sie über eine sehr große Ergebnismenge iterieren.

Bei Verwendung von Cursors müssen Sie einen Anfangscursor erstellen und in die Abfrageoptionen einschließen. Es gibt zwei Arten von Cursors, pro Abfrage und pro Ergebnis. Ein Cursor pro Abfrage bewirkt, dass ein separater Cursor dem vom Suchaufruf zurückgegebenen Ergebnisobjekt zugeordnet wird. Ein Cursor pro Ergebnis führt dazu, dass jedem bewerteten Dokument in den Ergebnissen ein Cursor zugeordnet wird.

Cursor pro Abfrage verwenden

Standardmäßig ist ein neu erstellter Cursor ein Cursor pro Abfrage. Dieser Cursor enthält die Position des letzten Dokuments, das in den Suchergebnissen zurückgegeben wurde. Er wird bei jeder Suche aktualisiert. Zum Auflisten aller übereinstimmenden Dokumente in einem Index führen Sie dieselbe Suche aus, bis das Ergebnis einen Nullcursor zurückgibt:

// index and queryString have already been defined

try {
    // create the initial cursor
    Cursor cursor = Cursor.newBuilder().build();

    do {
        // build options and query
        QueryOptions options = QueryOptions.newBuilder()
            .setCursor(cursor)
            .build();
        Query query = Query.newBuilder().setOptions(options).build(queryString);

        // search at least once
        Results<ScoredDocument> result = index.search(query);
        int numberRetrieved = result.getNumberReturned();
        cursor = result.getCursor();

        if (numberRetrieved > 0) {
            // process the matched docs
        }

    }
    while (cursor != null);
    // all done!
} catch (SearchException e) {
    // handle exception...
}

Cursor pro Ergebnis verwenden

Zum Erstellen von Cursorn pro Ergebnis müssen Sie die Property "perResult" des Cursors auf "true" festlegen, wenn Sie den Anfangscursor erstellen. Jedem Dokument, das von der Suche zurückgegeben wird, ist dann ein Cursor zugeordnet. Sie können mithilfe dieses Cursors eine neue Suche angeben, deren Ergebnisse bei einem bestimmten Dokument beginnen. Wenn Sie einen Cursor pro Ergebnis an die Suche übergeben, wird dem Ergebnis selbst kein Cursor pro Abfrage zugeordnet; result.getCursor() gibt null zurück, sodass Sie damit nicht testen können, ob Sie alle Übereinstimmungen abgerufen haben.

// index and queryString have already been defined

try {
    // create an initial per-result cursor
    Cursor cursor = Cursor.newBuilder().setPerResult(true).build();
    // build options and query
    QueryOptions options = QueryOptions.newBuilder()
        .setCursor(cursor)
        .build();
    Query query = Query.newBuilder().setOptions(options).build(queryString);
    Results<ScoredDocument> result = index.search(query);

    // process the matched docs
    cursor = null;
    for (ScoredDocument doc : result) {
        // discover some document of interest and grab its cursor
        if (...)
            cursor = doc.getCursor();
     }

    // Start the next search from the document of interest
    if (cursor != null) {
        options = QueryOptions.newBuilder()
            .setCursor(cursor)
            .build();
        query = Query.newBuilder().setOptions(options).build(queryString);
        result = index.search(query);
    }
} catch (SearchException e) {
    // handle exception
}

Cursor speichern und wiederherstellen

Ein Cursor kann als websicherer String serialisiert, gespeichert und dann für die spätere Verwendung wiederhergestellt werden:

String cursorString = cursor.toWebSafeString();
// Save the string ... and restore:
Cursor cursor = Cursor.newBuilder().build(cursorString));