Pesquisa com filtros

A pesquisa com filtros permite-lhe anexar informações categóricas aos seus documentos. Uma faceta é um par atributo/valor. Por exemplo, a faceta denominada "tamanho" pode ter os valores "pequeno", "médio" e "grande".

Ao usar facetas com a pesquisa, pode obter informações de resumo para ajudar a refinar uma consulta e analisar detalhadamente os resultados numa série de passos.

Isto é útil para aplicações como sites de compras, onde pretende oferecer um conjunto de filtros para os clientes restringirem os produtos que querem ver.

Os dados agregados de uma faceta mostram como os valores de uma faceta estão distribuídos. Por exemplo, a faceta "tamanho" pode aparecer em muitos dos documentos no seu conjunto de resultados. Os dados agregados dessa faceta podem mostrar que o valor "small" apareceu 100 vezes, "medium" 300 vezes e "large" 250 vezes. Cada par de faceta/valor representa um subconjunto de documentos no resultado da consulta. Uma chave, denominada refinamento, está associada a cada par. Pode incluir refinamentos numa consulta para obter documentos que correspondam à string de consulta e que tenham os valores de facetas correspondentes a um ou mais refinamentos.

Quando faz uma pesquisa, pode escolher os atributos a recolher e apresentar com os resultados ou pode ativar a deteção de atributos para selecionar automaticamente os atributos que aparecem com maior frequência nos seus documentos.

Adicionar facetas a um documento

Adicione facetas a um documento antes de adicionar o documento a um índice. Faça isto ao mesmo tempo que especifica os campos do 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)

Uma faceta é semelhante a um campo de documento; tem um nome e assume um valor.

Os nomes das facetas seguem as mesmas regras que os campos de documentos: os nomes são sensíveis a maiúsculas e minúsculas e só podem conter carateres ASCII. Têm de começar por uma letra e podem conter letras, dígitos ou um caráter de sublinhado. Um nome não pode ter mais de 500 carateres.

O valor de uma faceta pode ser uma string atómica (com um máximo de 500 carateres) ou um número (um valor de vírgula flutuante de precisão dupla entre -2 147 483 647 e 2 147 483 647).

Pode atribuir vários valores a uma faceta num documento adicionando uma faceta com o mesmo nome e tipo várias vezes, usando um valor diferente de cada vez.

Não existe limite para o número de valores que uma faceta pode ter. Também não existe limite para o número de facetas que pode adicionar a um documento nem para o número de facetas com nomes únicos num índice.

Tenha em atenção que, cada vez que usa uma faceta, esta pode assumir um valor atómico ou numérico. Uma faceta com o nome "size" pode ser anexada a um documento com o valor de string "small" e a outro documento com o valor numérico 8. Na verdade, o mesmo aspeto pode aparecer várias vezes no mesmo documento com ambos os tipos de valores. Não recomendamos a utilização de valores de átomos e números para a mesma faceta, apesar de ser permitido.

Embora um aspeto tenha um tipo específico quando o adiciona a um documento, os resultados da pesquisa reúnem todos os respetivos valores. Por exemplo, os resultados da faceta "tamanho" podem mostrar que existiram 100 instâncias do valor "pequeno", 150 instâncias de "médio" e 135 instâncias de valores numéricos no intervalo [4, 8). Os valores numéricos exatos e a respetiva distribuição de frequência não são apresentados.

Quando obtém um documento através de uma consulta, não pode aceder diretamente às respetivas facetas e valores. Tem de pedir que as informações de facetas sejam devolvidas com a sua consulta, conforme explicado na secção seguinte.

Usar uma pesquisa com filtros para obter informações de filtros

Pode pedir ao back-end de pesquisa para descobrir os atributos usados com mais frequência. Isto chama-se descoberta automática de atributos. Também pode obter informações de facetas explicitamente selecionando uma faceta por nome ou por nome e valor. Pode combinar os três tipos de obtenção de facetas numa única consulta.

Pedir informações de facetas não afeta os documentos devolvidos pela sua consulta. Pode afetar o desempenho. A realização de uma pesquisa com filtros com a profundidade predefinida de 1000 tem o mesmo efeito que definir o limite do avaliador das opções de ordenação como 1000.

Descoberta automática de facetas

A deteção automática de facetas procura as facetas que aparecem com mais frequência no total nos seus documentos. Por exemplo, suponhamos que os documentos que correspondem à sua consulta incluem uma faceta "cor" que aparece 5 vezes com o valor "vermelho", 5 vezes com o valor "branco" e 5 vezes com a cor "azul". Esta faceta tem uma contagem total de 15. Para fins de descoberta, seria classificado mais alto do que outra faceta "shade" que aparece nos mesmos documentos correspondentes 6 vezes com o valor "dark" e 7 vezes com o valor "light".

Tem de ativar a descoberta de facetas definindo-a na sua 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
                )
            )

Quando obtém facetas por deteção, por predefinição, apenas são devolvidos os 10 valores que ocorrem com mais frequência para uma faceta. Pode aumentar este limite até 100 usando o parâmetro FacetOptions discovery_limit.

Tenha em atenção que a descoberta automática de facetas não se destina a devolver todas as facetas possíveis e os respetivos valores. As facetas devolvidas da descoberta podem variar de execução para execução. Se quiser um conjunto fixo de facetas, use um parâmetro return_facets na sua consulta.

Os valores de string são devolvidos individualmente. Os valores numéricos de uma faceta descoberta são devolvidos num único intervalo [min max). Pode examinar este intervalo e criar um subintervalo mais pequeno para uma consulta posterior.

Selecionar facetas por nome

Para obter informações sobre uma faceta apenas pelo respetivo nome, adicione um parâmetro return_facets à sua consulta, incluindo o nome da faceta na 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
                )
            )

Quando obtém facetas por nome, por predefinição, apenas são devolvidos os 10 valores que ocorrem com mais frequência para uma faceta. Pode aumentar este limite até 20 usando o parâmetro FacetOptions discovery_value_limit.

Selecionar facetas por nome e valor

Para obter informações apenas sobre valores específicos de uma faceta, adicione um parâmetro return_facets que inclua um objeto FacetRequest com uma 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
                )
            )

Os valores num único FacetRequest têm de ser todos do mesmo tipo, ou seja, uma lista de valores de string ou, para números, uma lista de FacetRanges, que são intervalos fechados à esquerda (início) e abertos à direita (fim). Se o seu aspeto tiver uma combinação de valores de string e numéricos, adicione FacetRequests separados para cada um.

Opções

Pode controlar a pesquisa com filtros adicionando o parâmetro facet_options a uma chamada de consulta. Este parâmetro aceita uma única instância de FacetOptions. Use este parâmetro para substituir o comportamento predefinido da pesquisa com filtros.

options = FacetOptions(discover_facet_limit=5,
                       discover_facet_value_limit=10,
                       depth=6000);
Parâmetro Descrição Predefinição
discover_facet_limit Número de facetas a descobrir se a descoberta de facetas estiver ativada. Se for 0, a descoberta de facetas é desativada. 10
discover_facet_value_limit O número de valores a devolver para cada uma das principais facetas descobertas. 10
depth O número mínimo de documentos nos resultados da consulta a avaliar para recolher informações de atributos. 1000

A opção depth aplica-se aos três tipos de agregação de facetas: por nome, nome e valor, e deteção automática. As outras opções destinam-se apenas à deteção automática.

Tenha em atenção que a profundidade da faceta é normalmente muito superior ao limite de consultas. Os resultados das facetas são calculados para, pelo menos, o número de profundidade de documentos. Se tiver definido o limite de pontuação das opções de ordenação superior à profundidade, é usado o limite de pontuação.

A receber resultados de facetas

Quando usa parâmetros de pesquisa com filtros numa consulta, as informações de filtros agregadas são apresentadas com o próprio resultado da consulta.

Uma consulta tem uma lista de FacetResult. É apresentado um resultado na lista para cada faceta que apareceu num documento que correspondeu à sua consulta. Para cada resultado, recebe:

  • O nome do aspeto
  • Uma lista dos valores mais frequentes do aspeto. Para cada valor, existe uma contagem aproximada do número de vezes que apareceu e uma chave de refinamento que pode ser usada para obter os documentos que correspondem a esta consulta e valor de faceta.

Tenha em atenção que a lista de valores inclui a string e os valores numéricos de uma faceta. Se o aspeto foi descoberto automaticamente, os respetivos valores numéricos são devolvidos como um único intervalo [min max). Se pediu explicitamente uma faceta numérica com um ou mais intervalos na sua consulta, a lista vai conter um intervalo fechado-aberto [início fim) para cada intervalo.

A lista de valores de facetas pode não incluir todos os valores encontrados nos seus documentos, uma vez que as opções de consulta determinam quantos documentos examinar e quantos valores devolver.

As informações agregadas de cada faceta podem ser lidas nos resultados da pesquisa:

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

Por exemplo, uma consulta pode ter encontrado documentos que incluíam uma faceta "tamanho" com os valores de string e os valores numéricos. O FacetResult para este aspeto é construído da seguinte forma:

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)])

O parâmetro label é construído a partir de um valor de faceta. Para valores numéricos, label é a representação de um intervalo.

O refinement_key é uma string segura para a Web/URL que pode ser usada numa consulta posterior para obter os documentos que correspondem ao nome e valor da faceta desse resultado.

Usar facetas para refinar/filtrar uma consulta

O refinamento associado a cada FacetResultValue pode ser usado para restringir ainda mais os resultados de modo a incluir apenas documentos que tenham esses valores de faceta. Para refinar as consultas com uma ou mais destas chaves, transmita-as ao objeto de consulta:

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

Pode combinar refinamentos para uma ou mais facetas diferentes no mesmo pedido. Todos os refinamentos pertencentes à mesma faceta são unidos com um OR. Os refinamentos para diferentes facetas são combinados com AND.

Também é possível criar uma chave FacetRefinement personalizada manualmente. Consulte a documentação da classe para mais informações.