Gestionar los resultados de búsqueda

Cuando una llamada de consulta se completa normalmente, devuelve el resultado como un objeto Results. El objeto Results indica cuántos documentos coincidentes se han encontrado en el índice y cuántos se han devuelto. También incluye una colección de ScoredDocuments a juego. La colección suele contener una parte de todos los documentos coincidentes encontrados, ya que la búsqueda devuelve un número limitado de documentos cada vez que se llama. Si usas un desplazamiento o un cursor, puedes recuperar todos los documentos coincidentes, un subconjunto cada vez.

Resultados

// 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 función del valor de la limit opción de consulta, el número de documentos coincidentes devueltos en el resultado puede ser inferior al número encontrado. Recuerda que el número encontrado será una estimación si la precisión del número encontrado es inferior al número encontrado. Independientemente de cómo configures las opciones de búsqueda, una llamada search() no encontrará más de 10.000 documentos coincidentes.

Si se han encontrado más documentos de los que se han devuelto y quieres obtenerlos todos, debes repetir la búsqueda con un desplazamiento o un cursor, como se explica a continuación.

Documentos con puntuación

En los resultados de búsqueda se incluirá una colección de ScoredDocuments que coincidan con la consulta. Puedes recuperar la colección con el método getResults() o iterar sobre sus miembros directamente desde los resultados de búsqueda. Aquí se muestran ambos métodos:

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

De forma predeterminada, un documento con puntuación contiene todos los campos del documento original que se ha indexado. Si en las opciones de consulta se ha especificado setFieldsToReturn, solo aparecerán esos campos en los resultados cuando llames a getFields() en el documento. Si has usado addExpressionToReturn o setFieldsToSnippet para crear campos calculados, recupéralos por separado llamando a getExpressions() en el documento.

Usar desplazamientos

Si la búsqueda encuentra más documentos de los que puedes devolver a la vez, usa un desplazamiento para indexar la lista de documentos coincidentes. Por ejemplo, el límite de consultas predeterminado es de 20 documentos. Después de ejecutar una búsqueda por primera vez (con el desplazamiento 0) y obtener los primeros 20 documentos, obtén los 20 siguientes configurando el desplazamiento en 20 y volviendo a ejecutar la misma búsqueda. Repite la búsqueda y aumenta el desplazamiento cada vez en el número de documentos devueltos:

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

Los desplazamientos pueden ser ineficientes al iterar en un conjunto de resultados muy grande.

Usar cursores

También puedes usar cursores para obtener un subintervalo de resultados. Los cursores son útiles cuando quieres presentar los resultados de búsqueda en páginas consecutivas y quieres asegurarte de que no se omita ningún documento en el caso de que se modifique un índice entre consultas. Los cursores también son más eficientes cuando se itera en un conjunto de resultados muy grande.

Para usar cursores, debes crear un cursor inicial e incluirlo en las opciones de la consulta. Hay dos tipos de cursores: por consulta y por resultado. Un cursor por consulta hace que se asocie un cursor independiente al objeto de resultados devuelto por la llamada de búsqueda. Un cursor por resultado hace que se asocie un cursor a cada documento puntuado de los resultados.

Usar un cursor por consulta

De forma predeterminada, un cursor recién creado es un cursor por consulta. Este cursor contiene la posición del último documento devuelto en los resultados de la búsqueda. Se actualiza con cada búsqueda. Para enumerar todos los documentos que coinciden en un índice, ejecuta la misma búsqueda hasta que el resultado devuelva un cursor nulo:

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

Usar un cursor por resultado

Para crear cursores por resultado, debe definir la propiedad cursor perResult como true al crear el cursor inicial. Cuando se devuelvan los resultados de la búsqueda, cada documento tendrá un cursor asociado. Puedes usar ese cursor para especificar una nueva búsqueda con resultados que empiecen por un documento concreto. Ten en cuenta que, cuando envías un cursor por resultado a la búsqueda, no habrá ningún cursor por consulta asociado al resultado en sí. result.getCursor() devolverá null, por lo que no podrás usarlo para comprobar si has obtenido todas las coincidencias.

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

Guardar y restaurar cursores

Un cursor se puede serializar como una cadena segura para la Web, guardar y, a continuación, restaurar para usarlo más adelante:

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