Gérer les résultats de recherche

Lorsqu'un appel de requête se termine normalement, il renvoie le résultat sous la forme d'un objet Results. L'objet "Résultats" vous indique combien de documents correspondants ont été trouvés dans l'index et combien ont été renvoyés. Il comprend également une collection de ScoredDocuments correspondants. La collection contient généralement une partie de l'ensemble des documents correspondants trouvés, dans la mesure où la recherche renvoie un nombre limité de documents à chaque appel. À l'aide d'un décalage ou d'un curseur, vous pouvez récupérer tous les documents correspondants, un sous-ensemble à la fois.

Results

// 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...
}

En fonction de la valeur de l'option de requête limit, le nombre de documents correspondants renvoyés dans le résultat peut être inférieur au nombre trouvé. N'oubliez pas que le nombre trouvé sera une estimation si la précision du nombre trouvé est inférieure au nombre trouvé. Quelle que soit la façon dont vous configurez les options de recherche, un appel search() ne trouvera jamais plus de 10 000 documents correspondants.

Si le nombre de documents trouvés est supérieur au nombre de documents renvoyés, et si vous souhaitez tous les récupérer, vous devez répéter la recherche en utilisant un décalage ou un curseur, comme expliqué ci-dessous.

Documents notés

Les résultats de la recherche comprennent une collection de ScoredDocuments correspondant à la requête. Vous pouvez récupérer la collection à l'aide de la méthode getResults() ou en effectuant des itérations sur ses membres directement depuis les résultats de la recherche. Les deux méthodes sont décrites ci-dessous :

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

Par défaut, un document noté contient tous les champs du document original indexé. Si les options de requête spécifient setFieldsToReturn, seuls ces champs apparaissent dans les résultats lorsque vous appelez getFields() sur le document. Si vous avez utilisé addExpressionToReturn ou setFieldsToSnippet pour créer des champs calculés, récupérez-les séparément en appelant getExpressions() sur le document.

Utiliser des décalages

Si votre recherche trouve plus de documents qu'il n'est possible d'en renvoyer simultanément, utilisez un décalage à indexer dans la liste des documents correspondants. Supposons par exemple que la limite par défaut pour une requête est de 20 documents. Une fois que vous avez effectué une première recherche (avec un décalage de 0) et récupéré les 20 premiers documents, vous pouvez récupérer les 20 documents suivants en définissant le décalage sur 20 et en exécutant à nouveau la même recherche. Répétez la recherche, en incrémentant le décalage à chaque fois selon le nombre de documents renvoyés :

// 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...
}

Les décalages peuvent être inefficaces lors d'une itération sur un très grand ensemble de résultats.

Utiliser des curseurs

Les curseurs permettent de récupérer une sous-plage de résultats. Ils sont utiles lorsque vous souhaitez présenter les résultats de recherche dans des pages consécutives et vous assurer de n'oublier aucun document, dans l'éventualité où un index serait modifié entre les requêtes. Les curseurs sont également plus efficaces lors d'une itération sur un très grand ensemble de résultats.

Pour utiliser des curseurs, vous devez créer un curseur initial et l'inclure dans les options de requête. Il existe deux types de curseurs : par requête et par résultat. Un curseur par requête associe un curseur distinct à l'objet "results" renvoyé par l'appel de recherche. Un curseur par résultat permet d'associer un curseur à chaque document noté dans les résultats.

Utiliser un curseur par requête

Par défaut, un curseur récemment créé est un curseur par requête. Ce curseur contient la position du dernier document renvoyé dans les résultats de recherche. Il est mis à jour à chaque recherche. Pour énumérer tous les documents correspondants dans un index, exécutez la même recherche jusqu'à ce que le résultat renvoie un curseur "null" :

// 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...
}

Utiliser un curseur par résultat

Pour créer des curseurs par résultat, vous devez définir la propriété "perResult" du curseur sur "vrai" lorsque vous créez le curseur initial. Lorsque la recherche est renvoyée, un curseur est associé à chaque document. Vous pouvez utiliser ce curseur pour spécifier une nouvelle recherche de sorte que les résultats commencent par un document spécifique. Notez que lorsque vous faites passer un curseur par résultat à la recherche, aucun curseur par requête n'est associé au résultat. result.getCursor() retourne "null", vous ne pouvez ainsi pas l'utiliser pour vérifier si vous avez récupéré toutes les correspondances.

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

Enregistrer et restaurer des curseurs

Un curseur peut être sérialisé en tant que chaîne Web sécurisée, enregistré, puis restauré pour une utilisation ultérieure :

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