Analisadores para processamento de texto no Azure AI Search

Um analisador é um componente do mecanismo de pesquisa de texto completo que é responsável pelo processamento de cadeias de caracteres durante a indexação e a execução da consulta. O processamento de texto (também conhecido como análise lexical) é transformador, modificando uma cadeia de caracteres através de ações como estas:

  • Remover palavras não essenciais (stopwords) e pontuação
  • Dividir frases e palavras hifenizadas em partes componentes
  • Palavras minúsculas em maiúsculas
  • Reduza as palavras em formas de raiz primitivas para eficiência de armazenamento e para que as correspondências possam ser encontradas independentemente do tempo

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

Para campos dessa configuração, a análise ocorre durante a indexação quando os tokens são criados e, em seguida, novamente durante a execução da consulta quando as consultas são analisadas e o mecanismo verifica se há tokens correspondentes. É mais provável que ocorra uma correspondência quando o mesmo analisador é usado para indexação e consultas, mas você pode definir o analisador para cada carga de trabalho independentemente, dependendo de suas necessidades.

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 inteira para fazer a correspondência de padrões funcionar. Para garantir que os tokens de termo inteiro sejam preservados durante a indexação, você pode precisar de analisadores personalizados. Para obter mais informações sobre quando e por que os termos de consulta são analisados, consulte Pesquisa de texto completo no Azure AI Search.

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

Analisador padrão

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

Por padrão, o Azure AI Search usa o analisador Apache Lucene Standard (luceno padrão), que divide o texto em elementos seguindo as regras de "Segmentação de texto Unicode". O analisador padrão converte todos os caracteres para sua forma minúscula. Tanto os documentos indexados como os termos de pesquisa passam pela análise durante a indexação e o processamento da consulta.

Você pode substituir o padrão campo a campo. Os analisadores alternativos podem ser um analisador de linguagem para processamento linguístico, um analisador personalizado ou um analisador integrado da lista de analisadores disponíveis.

Tipos de analisadores

A lista a seguir descreve quais analisadores estão disponíveis no Azure AI Search.

Categoria Description
Analisador Lucene padrão Predefinição. Nenhuma especificação ou configuração é necessária. Este analisador de uso geral tem um bom desempenho para muitas linguagens e cenários.
Analisadores integrados Consumido como está e referenciado pelo nome. Existem dois tipos: linguagem e linguagem agnóstica.

Analisadores especializados (agnósticos à linguagem) são usados quando as entradas de texto exigem processamento especializado ou processamento mínimo. Exemplos de analisadores nesta categoria incluem Asciifolding, Keyword, Pattern, Simple, Stop, Whitespace.

Os analisadores de idiomas são usados quando você precisa de suporte linguístico avançado para idiomas individuais. O Azure AI Search suporta 35 analisadores de linguagem Lucene e 50 analisadores de processamento de linguagem natural da Microsoft.
Analisadores personalizados Refere-se a uma configuração definida pelo usuário de uma combinação de elementos existentes, consistindo em um tokenizador (obrigatório) e filtros opcionais (char ou token).

Alguns analisadores integrados, como Pattern ou Stop, suportam um conjunto limitado de opções de configuração. Para definir essas opções, crie um analisador personalizado, consistindo no analisador interno e em uma das opções alternativas documentadas em Analisadores integrados. Como em qualquer configuração personalizada, forneça um nome à sua nova configuração, como myPatternAnalyzer para distingui-la do analisador Lucene Pattern.

Especificando analisadores

A configuração de um analisador é opcional. Como regra geral, tente usar o analisador Lucene padrão padrão primeiro para ver como ele funciona. Se as consultas não conseguirem retornar os resultados esperados, mudar 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 obter mais informações, consulte Criar índice e também Adicionar analisadores personalizados.

  2. Ao definir um campo, defina sua propriedade "analyzer" como uma das seguintes: 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 aos analisadores de linguagem.

  4. Como alternativa, defina "indexAnalyzer" e "searchAnalyzer" para variar o analisador para cada carga de trabalho. Essas propriedades trabalham juntas como um substituto para a propriedade "analyzer", que deve ser null. Você pode usar analisadores diferentes para indexação e consultas se uma dessas atividades exigir uma transformação específica não necessária para a 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 soltar e recriar índices é rotina.

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

Para alterar o analisador de um campo existente, você terá que soltar e recriar todo o índice (não é possível reconstruir campos individuais). Para índices em produção, você pode adiar uma reconstrução criando um novo campo com a nova atribuição do analisador e começar a usá-lo no lugar do antigo. Use Update Index para incorporar o novo campo e mergeOrUpload para preenchê-lo. Mais tarde, como parte da manutenção de índice planejada, você pode limpar o índice para remover campos obsoletos.

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

Para adicionar um analisador personalizado a um índice existente, passe o sinalizador "allowIndexDowntime" no Update Index se quiser 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 conselhos sobre como trabalhar com analisadores.

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

O Azure AI Search permite especificar diferentes analisadores para indexação e pesquisa através das propriedades de campo "indexAnalyzer" e "searchAnalyzer". Se não for especificado, o conjunto do analisador com a propriedade do analisador é usado para indexação e pesquisa. Se o analisador não for especificado, o analisador Lucene padrão padrão será usado.

Uma regra geral é usar o mesmo analisador para indexação e consulta, a menos que requisitos específicos ditem o contrário. Certifique-se de testar minuciosamente. Quando o processamento de texto difere no momento da pesquisa e da indexação, você corre o risco de incompatibilidade entre termos de consulta e termos indexados quando as configurações do analisador de pesquisa e indexação não estão alinhadas.

Teste durante o desenvolvimento ativo

Substituir o analisador padrão requer uma reconstrução do índice. Se possível, decida quais analisadores usar durante o desenvolvimento ativo, antes de rolar um índice para a produção.

Inspecionar termos tokenizados

Se uma pesquisa não retornar os resultados esperados, o cenário mais provável é discrepâncias de token entre entradas de termos na consulta e termos tokenizados no índice. Se os tokens não forem os mesmos, as partidas não se materializam. Para inspecionar a saída do tokenizador, recomendamos o uso da API de análise como uma ferramenta de investigação. A resposta consiste em tokens, gerados por um analisador específico.

Exemplos REST

Os exemplos abaixo mostram definições de analisador para alguns cenários-chave.

Exemplo de analisador personalizado

Este exemplo ilustra uma definição de analisador com opções personalizadas. As opções personalizadas para filtros char, tokenizadores e filtros de token são especificadas separadamente como construções nomeadas e, em seguida, referenciadas na definição do analisador. Os elementos predefinidos são usados no estado em que se encontram e referenciados pelo nome.

Passando por este exemplo:

  • Os analisadores são uma propriedade da classe de 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 lugares.

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

  • Ele também define 2 filtros de caracteres personalizados "map_dash" e "remove_whitespace". O primeiro substitui todos os traços por sublinhados, enquanto o segundo remove todos os espaços. Os espaços precisam ser codificados em UTF-8 nas regras de mapeamento. Os filtros char são aplicados antes da tokenização e afetarão os tokens resultantes (o tokenizador padrão quebra no traço e espaços, mas não no 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 padrão é o padrão. Suponha que você queira substituir o padrão por um analisador predefinido diferente, como o analisador de padrões. Se você não estiver definindo opções personalizadas, só precisará especificá-las por nome na definição de campo.

O elemento "analisador" substitui o analisador padrão campo a campo. Não há substituição global. Neste exemplo, usa o analisador de padrões e text2, que não especifica um analisador, text1 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 indexação e operações de pesquisa

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

  {
     "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

Os campos que contêm cadeias de caracteres em idiomas diferentes podem usar um analisador de linguagem, enquanto outros campos mantêm o padrão (ou usam algum outro analisador predefinido ou personalizado). Se você usar um analisador de linguagem, ele deverá ser usado para operações de indexação e pesquisa. Os 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 do SDK do .NET, poderá acrescentar esses exemplos para usar ou configurar analisadores.

Atribuir um analisador de idiomas

Qualquer analisador usado no estado em que se encontra, 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 linguagem 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 no Azure AI Search.

Os analisadores personalizados são especificados de forma 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; }
      . . .
    }

Definir um analisador personalizado

Quando a personalização ou configuração for 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.

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

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

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óximos passos

Uma descrição detalhada da execução da consulta pode ser encontrada na Pesquisa de texto completo no Azure AI Search. O artigo usa exemplos para explicar comportamentos que podem parecer contraintuitivos na superfície.

Para saber mais sobre analisadores, consulte os seguintes artigos: