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 SearchResults. L'objet de résultats vous indique combien de documents correspondants ont été trouvés dans l'index et combien de documents correspondants ont été renvoyés. Il comprend également une collection de ScoredDocuments correspondants. Cette liste 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.

Résultats

def query_results(index, query_string):
    result = index.search(query_string)
    total_matches = result.number_found
    list_of_docs = result.results
    number_of_docs_returned = len(list_of_docs)
    return total_matches, list_of_docs, number_of_docs_returned

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 liste de ScoredDocuments correspondant à la requête. Vous pouvez parcourir cette liste afin de traiter un à un chaque document :

for scored_document in results:
        print(scored_document)

Par défaut, un document noté contient tous les champs du document original indexé. Si vos options de requête spécifient returned_fields, seuls ces champs apparaîtront dans la propriété fields du document. Si vous avez créé des champs calculés en spécifiant returned_expressions ou snippeted_fields, ces champs apparaissent séparément dans la propriété expressions du 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 :

def query_offset(index, query_string):
    offset = 0

    while True:
        # Build the query using the current offset.
        options = search.QueryOptions(offset=offset)
        query = search.Query(query_string=query_string, options=options)

        # Get the results
        results = index.search(query)

        number_retrieved = len(results.results)
        if number_retrieved == 0:
            break

        # Add the number of documents found to the offset, so that the next
        # iteration will grab the next page of documents.
        offset += number_retrieved

        # Process the matched documents
        for document in results:
            print(document)

Les décalages peuvent s'avérer 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" :

def query_cursor(index, query_string):
    cursor = search.Cursor()

    while cursor:
        # Build the query using the cursor.
        options = search.QueryOptions(cursor=cursor)
        query = search.Query(query_string=query_string, options=options)

        # Get the results and the next cursor
        results = index.search(query)
        cursor = results.cursor

        for document in results:
            print(document)

Utiliser un curseur par résultat

Pour créer des curseurs par résultat, vous devez définir la propriété "per_result" du curseur sur "true" lorsque vous créez le curseur initial. Lorsque les résultats de recherche sont renvoyés, 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() retournant "null", vous ne pouvez pas l'utiliser pour vérifier si vous avez récupéré toutes les correspondances.

def query_per_document_cursor(index, query_string):
    cursor = search.Cursor(per_result=True)

    # Build the query using the cursor.
    options = search.QueryOptions(cursor=cursor)
    query = search.Query(query_string=query_string, options=options)

    # Get the results.
    results = index.search(query)

    document_cursor = None
    for document in results:
        # discover some document of interest and grab its cursor, for this
        # sample we'll just use the first document.
        document_cursor = document.cursor
        break

    # Start the next search from the document of interest.
    if document_cursor is None:
        return

    options = search.QueryOptions(cursor=document_cursor)
    query = search.Query(query_string=query_string, options=options)
    results = index.search(query)

    for document in results:
        print(document)

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 :

def saving_and_restoring_cursor(cursor):
    # Convert the cursor to a web-safe string.
    cursor_string = cursor.web_safe_string
    # Restore the cursor from a web-safe string.
    cursor = search.Cursor(web_safe_string=cursor_string)