Analisadores para processamento de texto na IA do Azure Search

O analisador é um componente do mecanismo de pesquisa de texto completo responsável pelo processamento das cadeias de caracteres durante a indexação e execução de consulta. O processamento de texto (também conhecido como análise léxica) é transformativo, modificando uma cadeia de caracteres por meio de ações como estas:

  • Remover palavras não essenciais (palavras irrelevantes) e pontuação
  • Dividir frases e hifenizar palavras em partes do componente
  • Letras minúsculas de qualquer palavra em letras maiúsculas
  • Reduza as palavras em formulários raiz primitivos para eficiência de armazenamento e para que as correspondências possam ser encontradas independentemente de conjugação

A análise se aplica a Edm.String campos marcados como "pesquisáveis", que indica a pesquisa de texto completo.

Para campos com essa configuração, a análise ocorre durante a indexação quando os tokens são criados e, novamente durante a execução da consulta, quando as consultas são analisadas e o mecanismo verifica se há tokens correspondentes. Uma correspondência é mais provável de ocorrer quando o mesmo analisador é usado para indexação e consultas, mas você pode definir o analisador para cada carga de trabalho de maneira independente, dependendo dos seus requisitos.

Os tipos de consulta que não são pesquisa de texto completo, como filtros ou pesquisa difusa, não passam pela fase de análise no lado da consulta. Em vez disso, o analisador envia essas cadeias de caracteres diretamente para o mecanismo de pesquisa, usando o padrão que você fornece como base para a correspondência. Normalmente, esses formulários de consulta exigem tokens de cadeia de caracteres inteiras para fazer o trabalho de correspondência de padrões. Para garantir que tokens de termos inteiros sejam preservados durante a indexação, talvez seja necessário obter analisadores personalizados. Para obter mais informações sobre quando e por que os termos de consulta são analisados, consulte Pesquisa de texto completo na IA do Azure Search.

Para obter mais informações sobre análise lexical, ouça o seguinte clipe de vídeo para obter uma breve explicação.

Analisador padrão

Na IA do Azure Search, um analisador é invocado automaticamente em todos os campos de cadeia de caracteres marcados como pesquisáveis.

Por padrão, a IA do Azure Search usa o Analisador padrão do Apache Lucene (Lucene Standard), que divide o texto em elementos seguindo as regras de "Segmentação de texto Unicode". O analisador padrão converte todos os caracteres em sua forma em letras minúsculas. Documentos indexados e termos de pesquisa são submetidos a análise durante a indexação e o processamento de consultas.

Você pode substituir o padrão campo por campo. Analisadores alternativos são:

Tipos de analisadores

A lista a seguir descreve quais analisadores estão disponíveis na IA do Azure Search.

Categoria Descrição
Analisador Lucene padrão Padrão. Nenhuma especificação ou a configuração é necessária. Esse analisador de uso geral funciona bem em muitos dos idiomas e cenários.
Analisadores internos Consumido como está e referenciado pelo nome. Há dois tipos: idioma e independente de idioma.

Analisadores especializados (independentes de idioma) são usados quando as entradas de texto exigem processamento especializado ou o mínimo de processamento. Exemplos de analisadores nessa categoria incluem Asciifolding, Palavra-chave, Padrão, Simples, Parar, Espaço em branco.

Analisadores de idioma são usados quando você precisa de suporte linguístico avançado para idiomas individuais. A IA do Azure Search dá suporte a 35 analisadores de idioma Lucene e 50 analisadores de processamento de idioma natural Microsoft.
Analisadores personalizados Refere-se a uma configuração definida por usuário de uma combinação de elementos existentes, consistindo em um tokenizer (obrigatório) e filtros opcionais (char ou token).

Alguns analisadores internos, como Padrão ou Parar, dão suporte a um conjunto limitado de opções de configuração. Para definir essas opções, crie um analisador personalizado, consistindo de um analisador interno e uma das opções alternativas documentadas nos Analisadores internos. Como ocorre com qualquer configuração personalizada, forneça sua nova configuração com um nome, como myPatternAnalyzer para distingui-lo do analisador de padrões Lucene.

Especificando analisadores

A definição de um analisador é opcional. Como regra geral, tente usar o analisador Lucene padrão primeiro para ver como ele é executado. Se as consultas falharem ao retornar os resultados esperados, a alternância para um analisador diferente geralmente é a solução certa.

  1. Se você estiver usando um analisador personalizado, adicione-o ao índice de pesquisa na seção "analisador". Para saber mais, confira Criar Índice e também Adicionar analisadores personalizados.

  2. Ao definir um campo, defina a propriedade "Analyzer" como uma das opções a seguir: um analisador interno, como palavra-chave, um analisador de linguagem como en.microsoft, ou um analisador personalizado (definido no mesmo esquema de índice).

      "fields": [
     {
       "name": "Description",
       "type": "Edm.String",
       "retrievable": true,
       "searchable": true,
       "analyzer": "en.microsoft",
       "indexAnalyzer": null,
       "searchAnalyzer": null
     },
    
  3. Se você estiver usando um analisador de linguagem, deverá usar a propriedade "Analyzer" para especificá-lo. As propriedades "searchAnalyzer" e "indexAnalyzer" não se aplicam a analisadores de idioma.

  4. Como alternativa, defina "indexAnalyzer" e "searchAnalyzer" para variar o analisador para cada carga de trabalho. Essas propriedades funcionam juntas como substituto da propriedade "analyzer", que deve ser ficar em branco. Você usaria diferentes analisadores para indexação e consultas se uma dessas atividades exigisse uma transformação específica não necessária pela outra.

      "fields": [
     {
       "name": "ProductGroup",
       "type": "Edm.String",
       "retrievable": true,
       "searchable": true,
       "analyzer": null,
       "indexAnalyzer": "keyword",
       "searchAnalyzer": "standard"
     },
    

Quando adicionar analisadores

O melhor momento para adicionar e atribuir analisadores é durante o desenvolvimento ativo, quando descartar e recriar índices é a rotina.

Como os analisadores são usados para indexar os termos, você deve atribuir um analisador quando o campo é criado. Na verdade, a atribuição de um analisador ou indexAnalyzer a um campo que já foi criado fisicamente não é permitida (embora você possa alterar a propriedade searchAnalyzer a qualquer momento sem impacto no índice).

Para alterar o analisador de um campo existente, você precisará soltar e recriar o índice inteiro (não é possível recriar campos individuais). Para índices em produção, você pode adiar uma recompilação criando um novo campo com a nova atribuição do analisador e começar a usá-lo no lugar do antigo. Use Atualizar índice para incorporar o novo campo e mergeOrUpload para populá-lo. Posteriormente, como parte da manutenção planejada do índice, será possível limpar o índice para remover campos obsoletos.

Para adicionar um novo campo a um índice existente, chame Atualizar índice para adicionar o campo e mergeOrUpload para preenchê-lo.

Para adicionar um analisador personalizado a um índice existente, passe o sinalizador "allowIndexDowntime" no Atualizar índice se desejar evitar esse erro:

"Index update not allowed because it would cause downtime. In order to add new analyzers, tokenizers, token filters, or character filters to an existing index, set the 'allowIndexDowntime' query parameter to 'true' in the index update request. Note that this operation will put your index offline for at least a few seconds, causing your indexing and query requests to fail. Performance and write availability of the index can be impaired for several minutes after the index is updated, or longer for very large indexes."

Recomendações para trabalhar com analisadores

Esta seção oferece sugestões sobre como trabalhar com analisadores.

Um analisador para leitura/gravação, a menos que você tenha requisitos específicos

A IA do Azure Search permite especificar diferentes analisadores para indexação e pesquisa por meio das propriedades de campo "indexAnalyzer" e "searchAnalyzer". Se não forem especificados, o analisador definido com a propriedade analyzer será usado para indexação e pesquisa. Se o analisador não for especificado, o analisador Standard Lucene padrão será usado.

Uma regra geral é usar o mesmo analisador para indexação e consulta, a menos que requisitos específicos estabeleçam o contrário. Teste cuidadosamente. Quando o processamento de texto for diferente no momento de pesquisa e de indexação, você corre o risco de haver incompatibilidade entre os termos de consulta e os termos de indexação quando as configurações do analisador de pesquisa e de indexação não estiverem alinhadas.

Testar durante o desenvolvimento ativo

Substituir o analisador padrão requer um rebuild de índice. Se possível, escolha os analisadores a usar durante o desenvolvimento ativo antes de acumular um índice para produção.

Inspecionar termos indexados

Se uma pesquisa não retornar os resultados esperados, o cenário mais provável é discrepâncias de token entre as entradas de termo na consulta e os termos indexados no índice. Se os tokens não forem os mesmos, as correspondências não se materializarão. Para inspecionar a saída do indexador, é recomendável usar a API Analisar como uma ferramenta de investigação. A resposta é composta por tokens gerados por um analisador específico.

Exemplos de REST

Os exemplos abaixo mostram definições do analisador para alguns cenários principais.

Exemplo de analisador personalizado

Este exemplo ilustra uma definição de analisador com opções personalizadas. Opções personalizadas para filtros de caractere, tokenizadores e filtros de token são especificadas separadamente como constructos nomeados e, depois, referenciadas na definição do analisador. Elementos predefinidos são usados no estado em que se encontram e referenciados por nome.

Percorrendo este exemplo:

  • Analisadores são uma propriedade da classe do campo para um campo pesquisável.

  • Um analisador personalizado faz parte de uma definição de índice. Ele pode ser levemente personalizado (por exemplo, personalizando uma única opção em um filtro) ou personalizado em vários locais.

  • Nesse caso, o analisador personalizado é "my_analyzer" que, por sua vez, usa um tokenizador padrão personalizado "my_standard_tokenizer" e dois filtros de token: filtro de letras minúsculas e filtro asciifolding personalizado "my_asciifolding".

  • Ele também define dois filtros de char personalizados “map_dash” e “remove_whitespace”. O primeiro deles substitui todos os traços por sublinhados, enquanto o segundo remove todos os espaços. Os espaços precisam ser codificados com UTF-8 nas regras de mapeamento. Os filtros de char são aplicados antes da geração de tokens e afetarão os tokens resultantes (o tokenizador padrão faz uma quebra com traços e espaços, mas não com sublinhado).

  {
     "name":"myindex",
     "fields":[
        {
           "name":"id",
           "type":"Edm.String",
           "key":true,
           "searchable":false
        },
        {
           "name":"text",
           "type":"Edm.String",
           "searchable":true,
           "analyzer":"my_analyzer"
        }
     ],
     "analyzers":[
        {
           "name":"my_analyzer",
           "@odata.type":"#Microsoft.Azure.Search.CustomAnalyzer",
           "charFilters":[
              "map_dash",
              "remove_whitespace"
           ],
           "tokenizer":"my_standard_tokenizer",
           "tokenFilters":[
              "my_asciifolding",
              "lowercase"
           ]
        }
     ],
     "charFilters":[
        {
           "name":"map_dash",
           "@odata.type":"#Microsoft.Azure.Search.MappingCharFilter",
           "mappings":["-=>_"]
        },
        {
           "name":"remove_whitespace",
           "@odata.type":"#Microsoft.Azure.Search.MappingCharFilter",
           "mappings":["\\u0020=>"]
        }
     ],
     "tokenizers":[
        {
           "name":"my_standard_tokenizer",
           "@odata.type":"#Microsoft.Azure.Search.StandardTokenizerV2",
           "maxTokenLength":20
        }
     ],
     "tokenFilters":[
        {
           "name":"my_asciifolding",
           "@odata.type":"#Microsoft.Azure.Search.AsciiFoldingTokenFilter",
           "preserveOriginal":true
        }
     ]
  }

Exemplo de atribuição do analisador por campo

O analisador Standard é o padrão. Suponha que você deseja substituir o padrão com um analisador predefinido diferente, como o analisador de padrões. Se você não está definindo opções personalizadas, você só precisa especificá-lo pelo nome na definição do campo.

O elemento "analisador" substitui o analisador Standard, campo por campo. Não há nenhuma substituição global. Neste exemplo, text1 usa o analisador de padrões; já text2, que não especifica um analisador, usa o padrão.

  {
     "name":"myindex",
     "fields":[
        {
           "name":"id",
           "type":"Edm.String",
           "key":true,
           "searchable":false
        },
        {
           "name":"text1",
           "type":"Edm.String",
           "searchable":true,
           "analyzer":"pattern"
        },
        {
           "name":"text2",
           "type":"Edm.String",
           "searchable":true
        }
     ]
  }

Misturando analisadores para operações de indexação e de pesquisa

As APIs incluem atributos de índice para especificar diferentes analisadores para indexação e pesquisa. Os atributos searchAnalyzer e indexAnalyzer devem ser especificados como um par, substituindo o atributo analyzer individual.

  {
     "name":"myindex",
     "fields":[
        {
           "name":"id",
           "type":"Edm.String",
           "key":true,
           "searchable":false
        },
        {
           "name":"text",
           "type":"Edm.String",
           "searchable":true,
           "indexAnalyzer":"whitespace",
           "searchAnalyzer":"simple"
        },
     ],
  }

Exemplo de analisador de linguagem

Campos que contêm cadeias de caracteres em idiomas diferentes podem usar um analisador de idioma, enquanto outros campos mantêm o padrão (ou usam algum outro analisador predefinido ou personalizado). Se você usar um analisador de idioma, ele deverá ser usado para operações de indexação e de pesquisa. Campos que usam um analisador de linguagem não podem ter analisadores diferentes para indexação e pesquisa.

  {
     "name":"myindex",
     "fields":[
        {
           "name":"id",
           "type":"Edm.String",
           "key":true,
           "searchable":false
        },
        {
           "name":"text",
           "type":"Edm.String",
           "searchable":true,
           "indexAnalyzer":"whitespace",
           "searchAnalyzer":"simple"
        },
        {
           "name":"text_fr",
           "type":"Edm.String",
           "searchable":true,
           "analyzer":"fr.lucene"
        }
     ],
  }

Exemplos de C#

Se você estiver usando os exemplos de código .NET do SDK, poderá acrescentar esses exemplos para usar ou configurar os analisadores.

Atribuir um analisador de linguagem

Qualquer analisador usado como está, sem configuração, é especificado em uma definição de campo. Não há nenhum requisito para criar uma entrada na seção [analisadores] do índice.

Os analisadores de idiomas são usados no estado em que se encontram. Para usá-los, chame LexicalAnalyzer, especificando o tipo LexicalAnalyzerName fornecendo um analisador de texto com suporte na IA do Azure Search.

Os analisadores personalizados são especificados de maneira semelhante na definição de campo, mas para que isso funcione, você deve especificar o analisador na definição de índice, conforme descrito na próxima seção.

    public partial class Hotel
    {
       . . . 
        [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.EnLucene)]
        public string Description { get; set; }

        [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.FrLucene)]
        [JsonPropertyName("Description_fr")]
        public string DescriptionFr { get; set; }

        [SearchableField(AnalyzerName = "url-analyze")]
        public string Url { get; set; }
      . . .
    }

Atualizar um analisador personalizado

Quando a personalização ou configuração é necessária, adicione uma construção do analisador a um índice. Depois de defini-lo, você pode adicioná-lo à definição de campo, conforme demonstrado no exemplo anterior.

Criar um objeto CustomAnalyzer. Um analisador personalizado é uma combinação definida pelo usuário de um indexador conhecido, zero ou mais filtros de token e zero ou mais nomes de filtro de caracteres:

O exemplo a seguir cria um analisador personalizado chamado "url-analyze" que usa o indexador uax_url_email e o filtro de token em minúsculas.

private static void CreateIndex(string indexName, SearchIndexClient adminClient)
{
   FieldBuilder fieldBuilder = new FieldBuilder();
   var searchFields = fieldBuilder.Build(typeof(Hotel));

   var analyzer = new CustomAnalyzer("url-analyze", "uax_url_email")
   {
         TokenFilters = { TokenFilterName.Lowercase }
   };

   var definition = new SearchIndex(indexName, searchFields);

   definition.Analyzers.Add(analyzer);

   adminClient.CreateOrUpdateIndex(definition);
}

Próximas etapas

Uma descrição detalhada da execução da consulta pode ser encontrada na Pesquisa de texto completo na IA do Azure Search. O artigo usa exemplos para explicar os comportamentos que podem parecer um contador intuitivo na superfície.

Para saber mais sobre analisadores, confira os seguintes artigos: