Búsqueda por facetas

La búsqueda por facetas te permite adjuntar información categórica a tus documentos. Una faceta es un par de atributo y valor. Por ejemplo, la faceta llamada “tamaño” podría tener los valores “pequeño”, “mediano” y “grande”.

Mediante el uso de facetas con la búsqueda, puedes recuperar información de resumen a fin de precisar las consultas y “desglosar” los resultados en una serie de pasos.

Esto es útil para aplicaciones tales como los sitios de compras, en los que se quiere ofrecer a los clientes un conjunto de filtros para acotar la selección de productos que desean ver.

Los datos agregados de una faceta muestran cómo se distribuyen sus valores. Por ejemplo, la faceta “tamaño” puede aparecer en muchos de los documentos de tu conjunto de resultados. Los datos agregados de esta faceta podrían mostrar que el valor “pequeño” aparece 100 veces, “mediano” 300 veces y “grande” 250 veces. Cada par de faceta y valor representa un subconjunto de documentos en el resultado de la consulta. A cada par se asocia una clave denominada perfeccionamiento. Puedes incluir perfeccionamientos en una consulta para recuperar documentos que coincidan con la string de consulta y que tengan valores de faceta que se correspondan con uno o más perfeccionamientos.

Cuando llevas a cabo una búsqueda, puedes elegir qué facetas recopilar y mostrar con los resultados, o bien habilitar la detección de facetas para que se seleccionen de forma automática las que aparezcan con mayor frecuencia en tus documentos.

Agregado de facetas a un documento

Agrega facetas a un documento antes de agregar el documento a un índice. Hazlo al mismo tiempo que especificas los campos del documento:

def add_faceted_document(index):
    document = search.Document(
        doc_id="doc1",
        fields=[search.AtomField(name="name", value="x86")],
        facets=[
            search.AtomFacet(name="type", value="computer"),
            search.NumberFacet(name="ram_size_gb", value=8),
        ],
    )

    index.put(document)

La faceta es similar a un campo de un documento; tiene un nombre y recibe un valor.

Los nombres de las facetas siguen las mismas reglas que los campos de los documentos: los nombres distinguen entre mayúscula y minúscula, y solo pueden contener caracteres ASCII. Deben empezar con una letra y pueden incluir letras, dígitos o guiones bajos. El nombre no puede tener más de 500 caracteres.

El valor de una faceta puede ser una string atómica (de no más de 500 caracteres) o un número (valor de punto flotante de doble precisión entre -2,147,483,647 y 2,147,483,647).

Para asignar varios valores a una faceta de un documento, puedes agregar varias veces una faceta del mismo nombre y tipo, pero con un valor diferente en cada caso.

Las facetas pueden tener una cantidad ilimitada de valores. Tampoco hay restricciones en cuanto a la cantidad de facetas que puedes agregar a un documento o la cantidad de facetas con nombre único que puede incluir un índice.

Ten en cuenta que cada vez que uses una faceta, puede recibir un valor atómico o numérico. Es posible agregar una faceta con el nombre “tamaño” a un documento con el valor de string “pequeño” y a otro documento con el valor numérico 8. De hecho, la misma faceta puede aparecer varias veces en el mismo documento con ambos tipos de valores. No recomendamos usar valores atómicos y numéricos para la misma faceta aunque esté permitido.

Si bien cada faceta tiene un tipo específico cuando la agregas a un documento, los resultados de la búsqueda reúnen todos sus valores. Por ejemplo, los resultados para la faceta “tamaño” podrían mostrar que existen 100 instancias del valor “pequeño”, 150 instancias de “mediano” y 135 instancias de valores numéricos en el rango [4, 8). No se muestran los valores numéricos exactos ni su distribución de frecuencia.

Cuando recuperas un documento mediante una consulta, no puedes acceder directamente a sus facetas y valores. Debes solicitar que se muestre la información de la faceta con la consulta, como se explica en la sección siguiente.

Búsqueda por facetas para recuperar información sobre facetas

Puedes pedirle al backend de la búsqueda que detecte las facetas que se usan con más frecuencia. Esto se denomina "detección automática de facetas". También puedes recuperar información de facetas de manera explícita seleccionando una faceta por nombre o por nombre y valor. Puedes combinar las tres clases de recuperación de facetas en una misma consulta.

El pedido de información de las facetas no afectará los documentos que muestre la consulta. Sí puede afectar el rendimiento. Realizar una búsqueda por facetas con la profundidad predeterminada de 1,000 tiene el mismo efecto que configurar el límite del marcador de opciones de ordenamiento en 1,000.

Detección automática de facetas

La detección automática de facetas busca las facetas que aparecen con mayor frecuencia en la totalidad de tus documentos. Por ejemplo, imagina que los documentos que coinciden con tu consulta incluyen una faceta “color” que aparece 5 veces con el valor “rojo”, 5 veces con el valor “blanco” y 5 veces con el color “azul”. El recuento total de la faceta es 15. Para los fines de detección, se clasificaría en una posición superior a la de otra faceta “tono” que apareciera en los mismos documentos 6 veces con el valor “oscuro” y 7 veces con el valor “claro”.

Para habilitar la detección de facetas, debes configurarla en la consulta:

def facet_discovery(index):
    # Create the query and enable facet discovery.
    query = search.Query("name:x86", enable_facet_discovery=True)
    results = index.search(query)

    for facet in results.facets:
        print("facet {}.".format(facet.name))
        for value in facet.values:
            print(
                "{}: count={}, refinement_token={}".format(
                    value.label, value.count, value.refinement_token
                )
            )

Cuando recuperas facetas mediante la detección, según la configuración predeterminada, solo se muestran los 10 valores que aparecen con mayor frecuencia para una faceta. Puedes aumentar este límite hasta 100 mediante el parámetro FacetOptions discovery_limit.

Ten en cuenta que el objetivo de la detección automática de facetas no es mostrar todas las facetas posibles y sus valores. Las facetas que se muestran a partir de la detección pueden variar entre distintas ejecuciones. Si deseas consultar por un conjunto fijo de facetas, usa un parámetro return_facets en la consulta.

Los valores string se mostrarán de manera individual. Los valores numéricos de una faceta detectada se muestran en un único rango [mín. máx.). Puedes analizar ese rango y crear un subrango más pequeño para una consulta posterior.

Selecciona facetas por nombre

Para recuperar información acerca de una faceta solo por su nombre, agrega un parámetro return_facets a la consulta, incluido el nombre de la faceta en la lista:

def facet_by_name(index):
    # Create the query and specify to only return the "type" and "ram_size_gb"
    # facets.
    query = search.Query("name:x86", return_facets=["type", "ram_size_gb"])
    results = index.search(query)

    for facet in results.facets:
        print("facet {}".format(facet.name))
        for value in facet.values:
            print(
                "{}: count={}, refinement_token={}".format(
                    value.label, value.count, value.refinement_token
                )
            )

Cuando recuperas facetas por nombre, según la configuración predeterminada, solo se muestran los 10 valores que aparecen con mayor frecuencia para una faceta. Puedes aumentar este límite hasta 20 mediante el parámetro FacetOptions discovery_value_limit.

Selecciona facetas por nombre y valor

Para recuperar solo información sobre valores en particular de una faceta, agrega un parámetro return_facets que incluya un objeto FacetRequest con una lista de valores:

def facet_by_name_and_value(index):
    # Create the query and specify to return the "type" facet with values
    # "computer" and "printer" and the "ram_size_gb" facet with value in the
    # ranges [0,4), [4, 8), and [8, max].
    query = search.Query(
        "name:x86",
        return_facets=[
            search.FacetRequest("type", values=["computer", "printer"]),
            search.FacetRequest(
                "ram_size_gb",
                ranges=[
                    search.FacetRange(end=4),
                    search.FacetRange(start=4, end=8),
                    search.FacetRange(start=8),
                ],
            ),
        ],
    )

    results = index.search(query)
    for facet in results.facets:
        print("facet {}".format(facet.name))
        for value in facet.values:
            print(
                "{}: count={}, refinement_token={}".format(
                    value.label, value.count, value.refinement_token
                )
            )

Todos los valores de un FacetRequest deben ser del mismo tipo, ya sea una lista de valores string o, para números, una lista de FacetRanges, que son intervalos cerrados a la izquierda (comienzo) y abiertos a la derecha (final). Si tu faceta posee una combinación de valores numéricos y string, agrega distintas solicitudes FacetRequests para cada uno.

Opciones

Puedes controlar la búsqueda por facetas si agregas un parámetro facet_options a una llamada de consulta. Este parámetro toma una sola instancia de FacetOptions. Usa este parámetro para anular el comportamiento predeterminado de la búsqueda por facetas.

options = FacetOptions(discover_facet_limit=5,
                       discover_facet_value_limit=10,
                       depth=6000);
Parámetro Descripción Valor predeterminado
discover_facet_limit Cantidad de facetas para detectar si se activa la detección de facetas. Si el valor es 0, la detección de facetas se inhabilita. 10
discover_facet_value_limit Cantidad de valores que se muestran para cada una de las facetas descubiertas más importantes. 10
depth La cantidad mínima de documentos en los resultados de la consulta a evaluarse para recopilar información de la faceta. 1,000

La opción depth se aplica a los tres tipos de agregación de facetas: por nombre, por nombre y valor, y autodetección. Las otras opciones son solo para la autodetección.

Ten en cuenta que la profundidad de las facetas suele mucho mayor que el límite de la consulta. Los resultados de las facetas se calculan como mínimo para el valor de profundidad de los documentos. Si configuraste el límite del marcador de opciones de ordenamiento en un valor superior al de la profundidad, se usará el límite del marcador.

Recuperación de resultados de facetas

Cuando usas parámetros de búsqueda por facetas en una consulta, la agregación de la información de las facetas se muestra junto con el resultado de la consulta.

La consulta tendrá una lista de FacetResult. Habrá un resultado en la lista por cada faceta que apareció en un documento que coincidió con tu consulta. Para cada resultado, obtendrás lo siguiente:

  • El nombre de la faceta.
  • Una lista de los valores más frecuentes de la faceta. A cada valor le corresponde un conteo de la cantidad de veces que apareció y una clave de perfeccionamiento que se puede usar con el propósito de recuperar los documentos que coinciden con esta consulta y con el valor de la faceta.

Ten en cuenta que la lista de valores incluirá los valores numéricos y las strings de la faceta. Si la faceta se detectó de forma automática, sus valores numéricos se mostrarán como un único intervalo [mín., máx.). Si en la consulta solicitaste de forma explícita una faceta numérica con uno o más rangos, la lista mostrará un intervalo cerrado-abierto [inicio, fin) por cada rango.

La lista de valores de la faceta puede no incluir todos los valores encontrados en los documentos, ya que las opciones de la consulta determinan cuántos documentos se examinan y cuántos valores se muestran.

La agregación de la información de cada faceta puede leerse desde los resultados de la búsqueda:

query = search.Query(...)
results = index.search(query)
for facet_info in results.facets:
  ...

Por ejemplo, una consulta podría encontrar documentos que incluyan una faceta “tamaño” con valores string y numéricos. Los valores FacetResult de esta faceta tendrían el siguiente formato:

FacetResult(name='size', values=[
  FacetResultValue(label='[8, 10)', 22, refinement=refinement_key),
  FacetResultValue(label='small', 100, refinement=refinement_key),
  FacetResultValue(label='medium', 300, refinement=refinement_key),
  FacetResultValue(label='large', 250, refinement=refinement_key)])

El parámetro label se crea a partir de un valor de faceta. Para los valores numéricos, label es la representación de un rango.

refinement_key es una string segura para la Web y URL que puede usarse en una consulta posterior a fin de recuperar los documentos que coincidan con el nombre y el valor de faceta de ese resultado.

Usa facetas para definir mejor o filtrar una consulta

El perfeccionamiento asociado con cada FacetResultValue se puede usar para reducir aún más los resultados y solo incluir los documentos que tengan esos valores de faceta. Para definir mejor las consultas con una o más de estas claves, pásalas al objeto de consulta:

query = search.Query(..., facet_refinements=[refinement_key1, refinement_key2, refinement_key3])

Puedes combinar perfeccionamientos para una o más facetas diferentes en la misma solicitud. Todos los perfeccionamientos que pertenezcan a la misma faceta se unirán con un operador OR. Los perfeccionamientos de facetas diferentes se combinarán con AND.

También se puede crear una clave FacetRefinement personalizada de forma manual. Consulta la documentación sobre clases para obtener más información.