Análise de cinco documentos
No Elasticsearch, o conteúdo do texto do documento é analisado por meio de um analisador, e o conteúdo do texto é segmentado e padronizado, processo denominado análise de documento .
5.1 O que é um analisador?
No Elasticsearch, o analisador é um módulo de software responsável principalmente por duas funções: Tokenização (segmentação de palavras) e Normalização (normalização).
-
Tokenização
A tokenização, ou seja, tokenização, é o processo de divisão de sentenças em palavras individuais e segue certas regras.
-
Normalização
Normalização, ou seja, normalização é o processo de processamento, conversão, modificação e enriquecimento de segmentos de palavras (palavras) na forma de lematização , sinônimos , palavras irrelevantes e outros recursos .
O analisador consiste em um tokenizer , zero ou mais filtros de caracteres e zero ou mais filtros de token. Sua estrutura é mostrada na figura abaixo.
-
filtro de caracteres
Processa o conteúdo do texto de entrada, aplicado ao nível do caractere.
-
tokenizador
O fluxo de caracteres processado pelo filtro de caracteres é posteriormente processado e o texto é dividido em vários termos de acordo com as regras.
-
filtro de termo
Os termos segmentados pelo tokenizer são processados posteriormente.
Filtros de caracteres, tokenizadores e filtros de termos serão apresentados em detalhes nos capítulos subsequentes.
- O processo geral de trabalho do analisador
- O conteúdo do texto deve primeiro ser filtrado e processado pelo filtro de caracteres
- O segmentador de palavras processa o conteúdo do texto processado na primeira etapa de acordo com as regras especificadas e o divide em vários termos.
- Processe ainda mais os termos divididos na segunda etapa
- Adicione os termos processados na terceira etapa ao índice invertido.
5.2 Filtro de caracteres
5.2.1 Função
Os filtros de caracteres são aplicados no nível do caractere e cada caractere do texto passa por esses filtros em ordem. Esses filtros podem executar as seguintes funções específicas:
-
Remova caracteres indesejados do fluxo de entrada
Por exemplo, você pode limpar do texto de entrada
, e outras tags HTML.
-
Adicionar ou substituir outros caracteres em um stream existente
Por exemplo, as letras gregas são substituídas por palavras inglesas equivalentes (0 e 1 são substituídos por falso e verdadeiro).
O Elasticsearch fornece três filtros de caracteres que podemos usar para construir nossos próprios analisadores personalizados.
5.2.2 filtro de caracteres html_strip
-
efeito
O filtro de caracteres html_strip remove elementos HTML como e decodifica entidades HTML como &.
-
Exemplo
Use o filtro de caracteres html_strip para processar o seguinte texto
<h1>html_strip & test hellow</h1>
Após o texto passar por esse filtro de caracteres, apenas o texto "html_strip & test hellow" permanece. Podemos enviar solicitações get/post para http://localhost:9200/_analyze e adicionar os seguintes parâmetros ao corpo da solicitação
{ "text":"<h1>html_strip & test hellow</h1>", // 要解析的文本内容 "tokenizer": "standard", // 使用的分词器是标准分词器,后面小节会进行讲解 "char_filter": ["html_strip"] // 使用的字符过滤器 }
Os resultados podem ser obtidos da seguinte forma:
// 返回值 { "tokens": [ { "token": "html_strip", "start_offset": 4, "end_offset": 14, "type": "<ALPHANUM>", "position": 0 }, { "token": "test", "start_offset": 17, "end_offset": 21, "type": "<ALPHANUM>", "position": 1 }, { "token": "hellow", "start_offset": 22, "end_offset": 28, "type": "<ALPHANUM>", "position": 2 } ] }
Como você pode ver no valor de retorno acima, após ser processado pelo filtro de caracteres html_strip e pelo segmentador de palavras padrão, o Elasticsearch divide o conteúdo do texto de entrada em três palavras e os elementos HTML foram removidos dele.
O tokenizer padrão dividirá o conteúdo do texto de acordo com palavras individuais e ignorará alguns caracteres especiais, como &, que serão explicados posteriormente.
-
Mantenha alguns elementos HTML
Usar o filtro de caracteres html_strip removerá todos os elementos HTML do conteúdo do texto. Ao mesmo tempo, o filtro de caracteres html_strip suporta a retenção de alguns elementos HTML. Podemos usar o atributo estendido escaped_tags do filtro de caracteres html_strip para especificar os elementos HTML que precisam ser retidos.
Por exemplo, inserimos o seguinte texto
<pre><h1>html_strip & test hellow</h1></pre>
Queremos que o seguinte texto permaneça após passar pelo filtro de caracteres html_strip
<pre>html_strip & test hellow</pre>
Neste momento, não podemos mais simplesmente usar o filtro de caracteres html_strip, precisamos customizar um analisador. ( Cada parâmetro será explicado em detalhes posteriormente, aqui nos concentramos principalmente no atributo estendido escaped_tags do filtro de caracteres html_strip )
Crie um índice usando um analisador personalizado
// PUT http://localhost:9200/character-filter-test // body内容 { "settings": { "analysis": { "analyzer": { // 当前索引中的分析器集合 "test_html_strip_filter_analyzer": { // 自定义的分析器名称 "tokenizer": "keyword", "char_filter": ["my_html_strip_filter"] // 自定义的分析器使用的字符过滤器集合 } }, "char_filter": { // 当前索引中的字符过滤器集合 "my_html_strip_filter": { // 自定义字符过滤器的名称 "type": "html_strip", // 字符过滤器类型为html_strip "escaped_tags": ["pre"] // 要保留的html元素名 } } } } }
Analise texto usando um analisador personalizado
// POST http://localhost:9200/character-filter-test/_analyze // body内容 { "text":"<pre><h1>html_strip & test hellow</h1></pre>", // 要分析的文本内容 "analyzer": "test_html_strip_filter_analyzer" // 使用的分析器名称 }
O resultado é o seguinte:
Como pode ser visto nos resultados, não há tag h1 no resultado após a segmentação de palavras, mas há uma tag pré.
Observação: os resultados aqui contêm &. Isso ocorre porque o tokenizer em nosso analisador usa palavras-chave. Isso será apresentado em detalhes posteriormente. O foco aqui é apenas manter a tag pré.
5.2.3 mapeamento de filtro de caracteres
-
efeito
O filtro de caracteres de mapeamento substitui qualquer ocorrência da sequência especificada pela sequência de substituição especificada.
-
Exemplo
Substitua “CN” no conteúdo do texto inserido por “China”.
// POST http://localhost:9200/_analyze // body内容 { "text":"I come from CN", "tokenizer": "keyword", "char_filter": [{ "type":"mapping", "mappings":[ "CN => 中国" ] }] }
O resultado é o seguinte:
Você pode ver que CN no conteúdo foi substituído pela China
-
Use um analisador personalizado
No uso formal, geralmente é usado em conjunto com um analisador personalizado.
Crie índice com filtro de caracteres de mapeamento personalizado
// PUT http://localhost:9200/mapping-filter-test // body内容 { "settings": { "analysis": { "analyzer": { "test_mapping_filter_analyzer": { "tokenizer": "keyword", "char_filter": ["my_mapping_filter"] } }, "char_filter": { "my_mapping_filter": { "type": "mapping", "mappings": [ "CN => 中国", "HUBEI => 湖北", "WUHAN => 武汉" ] } } } } }
Testar segmentação de palavras
// GET http://localhost:9200/mapping-filter-test/_analyze // body内容 { "text":"I come from WUHAN,HUBEI,CN", "analyzer": "test_mapping_filter_analyzer" }
O resultado é o seguinte:
Como você pode ver, o conteúdo do texto inserido foi substituído pelo texto de acordo com o mapeamento que configuramos.
-
Usar arquivos de configuração
Quando temos muitos mapeamentos, é inconveniente manter esse método de script. Portanto, o Elasticsearch suporta a leitura de arquivos no diretório especificado configurando o atributo mappings_path do filtro de caracteres de mapeamento para obter mapeamentos de mapeamento.
No subdiretório config do diretório de instalação do Elasticsearch, crie uma pasta de análise, coloque o arquivo my_mapping.txt nela e mantenha o mapeamento correspondente no arquivo, conforme mostrado na figura abaixo.
Nota: O arquivo txt deve ser codificado em UTF-8 e cada mapeamento precisa ser separado por novas linhas .
Crie um índice para teste
// PUT http://localhost:9200/mapping-filter-test2 // body内容 { "settings": { "analysis": { "analyzer": { "test_mapping_filter_analyzer": { "tokenizer": "keyword", "char_filter": ["my_mapping_filter"] } }, "char_filter": { "my_mapping_filter": { "type": "mapping", "mappings_path": "analysis/my_mapping.txt" } } } } }
Mappings_path precisa especificar o arquivo de configuração a ser lido. O caminho pode ser um caminho relativo ou um caminho absoluto baseado no diretório de configuração.
// GET http://localhost:9200/mapping-filter-test2/_analyze // body内容 { "text":"I come from WUHAN,HUBEI,CN", "analyzer": "test_mapping_filter_analyzer" }
O resultado é o seguinte:
5.2.4 filtro de caracteres pattern_replace
-
efeito
O filtro de caracteres pattern_replace substitui qualquer caractere que corresponda a uma expressão regular pela substituição especificada.
-
Exemplo
Aqui, usamos diretamente um analisador personalizado para demonstração, substituindo o número de telefone no conteúdo do texto pelo chinês “Este é um número de telefone”.
// PUT http://localhost:9200/pattern-replace-filter-test // body内容 { "settings": { "analysis": { "analyzer": { "test_pattern_replace_filter_analyzer": { "tokenizer": "keyword", "char_filter": ["my_pattern_replace_filter"] } }, "char_filter": { "my_pattern_replace_filter": { "type": "pattern_replace", "pattern": "^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$", "replacement": "这是一段电话号码" } } } } }
teste
// GET http://localhost:9200/pattern-replace-filter-test/_analyze // body内容 { "text":"13111111111", "analyzer": "test_pattern_replace_filter_analyzer" }
O resultado é o seguinte:
5.3 Tokenizador
5.3.1 Função
O segmentador de palavras é um meio de analisar e processar texto. A lógica básica de processamento é dividir o texto original em vários termos de granulação menor de acordo com as regras de segmentação de palavras pré-estabelecidas . O tamanho da granularidade depende das regras do segmentador de palavras .
Funciona após o filtro de caracteres (se houver).
O sistema possui alguns separadores de palavras integrados. Apresentaremos em detalhes vários separadores de palavras comumente usados. Para outros separadores de palavras, consulte a documentação oficial .
5.3.2 tokenizador padrão
-
efeito
Este tokenizer dividirá o texto em vários termos de acordo com os limites das palavras definidos pelo algoritmo de segmentação de texto Unicode , e o tokenizer removerá a maioria dos sinais de pontuação.
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text":"I like steak !", "tokenizer": "standard" }
O resultado é o seguinte:
Como você pode ver, cada palavra é dividida em um termo e o ponto de exclamação é removido.
5.3.3 tokenizador de letras
-
efeito
Este tokenizer irá segmentar o texto não alfabético, ou seja, quando houver texto não alfabético entre palavras adjacentes, ele será segmentado e o texto não alfabético também será removido.
Nota: Ao encontrar caracteres chineses, eles serão processados de acordo com as letras, ou seja, ao encontrar caracteres chineses, eles não serão separados.
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text":"I,like&steak和西红柿!and#you", "tokenizer": "letter" }
O resultado é o seguinte:
5.3.4 tokenizador de espaço em branco
-
efeito
Este tokenizer se divide quando espaços são encontrados.
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text":"I like&steak!", "tokenizer": "whitespace" }
O resultado é o seguinte:
5.3.5 tokenizador de letras minúsculas
-
efeito
Este tokenizer é semelhante ao tokenizer de letras. Ele dividirá o texto não alfabético e converterá cada termo segmentado em letras minúsculas. Esse filtro também descartará termos de texto não alfabéticos.
É equivalente a uma combinação de tokenizador de letras e filtro de termos minúsculos, mas tem desempenho superior.
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text":"I,like&steak和西红柿!and#you", "tokenizer": "lowercase" }
O resultado é o seguinte:
5.3.6 tokenizador clássico
-
efeito
Este tokenizer segmenta texto com base em regras gramaticais e é muito útil para segmentar documentos em inglês . Funciona muito bem com siglas, nomes de empresas, endereços de e-mail e nomes de hosts da Internet.
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text":"My mail is [email protected]", "tokenizer": "classic" }
O resultado é o seguinte:
5.3.7 tokenizador de palavras-chave
-
efeito
Este tokenizer é um tokenizer "noop" que pega qualquer texto fornecido e gera exatamente o mesmo texto como um único termo. Ele pode ser combinado com filtros de termos para normalizar a saída, como endereços de e-mail em letras minúsculas.
Ou seja, trate o texto de entrada como um todo
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text":"I like steak !", "tokenizer": "keyword" }
O resultado é o seguinte:
5.3.8 tokenizador de padrão
-
efeito
Isso usa expressões regulares para dividir o texto em termos quando os separadores de palavras são correspondidos ou para capturar o texto correspondente como termos.
O modo padrão é \W+, que divide o texto quando são encontrados caracteres que não sejam palavras.
-
Exemplo
Divida o texto em termos ao combinar separadores de palavras
// GET http://localhost:9200/_analyze // body内容 { "text":"test,pattern,tokenizer!!!", "tokenizer": { "type":"pattern", "pattern":"," } }
De acordo com "," segmentação de palavras
O resultado é o seguinte:
Capture texto correspondente como termos
// GET http://localhost:9200/_analyze // body内容 { "text":"\"test\"\"pattern,tokenizer!!!\"", "tokenizer": { "type":"pattern", "pattern":"\"((?:\\\\\"|[^\"]|\\\\\")+)\"", "group":1 } }
Capture valores entre aspas duplas
O grupo aqui se refere à API group() do objeto Matcher do Java.
O resultado é o seguinte:
5.4 Filtro de termos
5.4.1 Função
Os filtros de termos aceitam um fluxo de termos do tokenizer e podem modificar termos (por exemplo, letras minúsculas), remover termos (por exemplo, remover palavras irrelevantes) ou adicionar termos (por exemplo, sinônimos).
O sistema possui alguns filtros de termos integrados. Apresentaremos em detalhes vários filtros de termos comumente usados. Para outros filtros de termos, consulte a documentação oficial .
5.4.2 filtro de termo em minúsculas
-
efeito
Este filtro de termos altera cada termo de letras maiúsculas para minúsculas, como Homem para homem, e oferece suporte à conversão de letras minúsculas para grego, irlandês e turco.
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text":"I Like StEak !", "tokenizer": "keyword", "filter" : ["lowercase"] }
O resultado é o seguinte:
5.4.3 filtro de termos maiúsculos
-
efeito
Este filtro de termos mudará cada termo de minúsculas para maiúsculas, por exemplo, man para MAN.
Perceber:
Dependendo do idioma, um caractere maiúsculo pode ser mapeado para vários caracteres minúsculos. Usar o filtro de letras maiúsculas pode resultar na perda de informações de caracteres minúsculos, por isso é mais recomendado usar o filtro de termos em letras minúsculas
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text":"I Like StEak !", "tokenizer": "keyword", "filter" : ["uppercase"] }
O resultado é o seguinte:
5.4.4 filtro de comprimento e prazo
-
efeito
Remove termos menores ou maiores que o comprimento de caracteres especificado. Por exemplo, você pode excluir termos com menos de 2 caracteres e termos com mais de 5 caracteres.
Perceber:
Este filtro remove termos inteiros que não atendem aos critérios. Se você quiser encurtar os termos para um comprimento específico, use o filtro de termo truncado .
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text": "I Like StEak !", "tokenizer": "standard", "filter": [{ "type": "length", "min": 2, "max": 4 }] }
O resultado é o seguinte:
5.4.5 filtro de termo truncado
-
efeito
Este filtro trunca os termos que excedem o limite de caracteres especificado. Esse limite é padronizado como 10, mas pode ser personalizado usando o parâmetro length.
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text": "I Like StEak !", "tokenizer": "keyword", "filter": [{ "type": "truncate", "length": 5 }] }
O resultado é o seguinte:
5.4.6 Filtro de termo dobrável ASCII
-
efeito
Este filtro converte caracteres alfabéticos, numéricos e simbólicos (os primeiros 127 caracteres ASCII) que não estão no bloco Basic Latin Unicode em seus equivalentes ASCII (se presentes). Por exemplo, o filtro muda à para a.
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text": "açaí à la carte", "tokenizer": "keyword", "filter": ["asciifolding"] }
O resultado é o seguinte:
5.4.7 filtro de termo de parada
-
efeito
Este filtro remove palavras irrelevantes dos termos.
Se não houver palavras irrelevantes personalizadas, o filtro excluirá as seguintes palavras irrelevantes em inglês por padrão:
a, an, e, são, como, em, ser, mas, por, para, se, em, em, é, não, não, de, em, ou, tal, que, o, seu, então, lá, estes, eles, isto, para, foi, irá, com
O filtro oferece suporte a listas de palavras irrelevantes predefinidas para vários idiomas além do inglês, e você também pode especificar suas próprias palavras irrelevantes como uma matriz ou arquivo.
Por favor, verifique a documentação oficial para configuração detalhada
-
Exemplo
Aqui estão apenas exemplos simples.
// GET http://localhost:9200/_analyze // body内容 { "text": "a quick fox jumps over the lazy dog", "tokenizer": "standard", "filter": ["stop"] }
O resultado é o seguinte:
5.5 Analisadores integrados comuns
Elasticsearch fornece alguns analisadores integrados para os usuários usarem.
A seguir, apresentaremos alguns analisadores integrados comumente usados. Para analisadores integrados mais detalhados, consulte a documentação oficial.
5.5.1 analisador padrão
-
efeito
Este analisador é o analisador padrão e é usado por padrão se nenhum analisador for especificado. Ele fornece uma função de segmentação de palavras baseada no algoritmo de segmentação de texto Unicode, que remove a maioria dos sinais de pontuação, converte termos em letras minúsculas e suporta a remoção de palavras irrelevantes. É adequado para a maioria dos idiomas, mas o suporte para chinês não é ideal: será dividido caractere por caractere e segmentado por palavra.
-
composição
-
filtro de caracteres
nenhum
-
tokenizador
tokenizador padrão
-
filtro de termo
filtro de termo em minúsculas
filtro de termo de parada (não habilitado por padrão)
-
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text":"I Like StEak !", "analyzer": "standard" }
O resultado é o seguinte:
5.5.2 analisador simples
-
efeito
O analisador divide o texto em termos com quaisquer caracteres não alfabéticos (como números, espaços, hifens e apóstrofos), descartando caracteres não alfabéticos e convertendo letras maiúsculas em minúsculas.
-
composição
-
filtro de caracteres
nenhum
-
tokenizador
tokenizador em minúsculas
-
filtro de termo
nenhum
-
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text":"I Like &StEak 和西红柿 2333 !", "analyzer": "simple" }
O resultado é o seguinte:
5.5.3 parar o analisador
-
efeito
Este analisador é igual ao analisador simples, mas adiciona suporte para remoção de palavras irrelevantes.
-
composição
-
filtro de caracteres
nenhum
-
tokenizador
tokenizador em minúsculas
-
filtro de termo
parar filtro de termo
-
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text":"I Like &StEak the 和西红柿 2333 !", "analyzer": "stop" }
O resultado é o seguinte:
5.5.4 analisador de padrões
-
efeito
Este analisador usa expressões regulares para dividir o texto em termos individuais e converter termos de letras maiúsculas para minúsculas. As expressões regulares devem corresponder aos delimitadores, não aos termos em si. As expressões regulares são padronizadas como \W+ (todos os caracteres que não são palavras).
Nota: Expressões regulares Java são usadas aqui. Se o desempenho das expressões regulares for ruim, isso pode causar exceções de stackoverflow.
-
composição
-
filtro de caracteres
nenhum
-
tokenizador
tokenizador de padrão
-
filtro de termo
filtro de termo em minúsculas
filtro de termo de parada (não habilitado por padrão)
-
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text":"I,Like&StEak,the,和西红柿,2333 !", "analyzer":"pattern" }
O resultado é o seguinte:
5.5.5 analisador de espaços em branco
-
efeito
O analisador divide o texto em termos quando são encontrados caracteres de espaço em branco.
-
composição
-
filtro de caracteres
nenhum
-
tokenizador
tokenizador de espaço em branco
-
filtro de termo
nenhum
-
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text":"I Like &StEak the 和西红柿 2333 !", "analyzer":"whitespace" }
O resultado é o seguinte:
5.5.6 analisador de palavras-chave
-
efeito
Este analisador é um analisador "noop" que retorna toda a string de entrada como um único termo.
-
composição
-
filtro de caracteres
nenhum
-
tokenizador
tokenizador de palavra-chave
-
filtro de termo
nenhum
-
-
Exemplo
// GET http://localhost:9200/_analyze // body内容 { "text":"I Like &StEak the 和西红柿 2333 !", "analyzer":"keyword" }
O resultado é o seguinte:
5.6 Analisador Personalizado
Quando os analisadores integrados do Elasticsearch não conseguem atender às necessidades do negócio, podemos definir analisadores personalizados para atender às necessidades do negócio.
Os analisadores personalizados também são compostos por 0 ou mais filtros de caracteres + um tokenizer + 0 ou mais filtros de termos .
Os parâmetros de configuração comumente usados do analisador são os seguintes :
nome do parâmetro | significado |
---|---|
tipo | Tipo de analisador. Aceita tipos de analisadores integrados. Para analisadores customizados, use custom ou omita esse parâmetro. |
tokenizador | Especifique o tokenizer a ser usado, que pode ser um tokenizer integrado ou um tokenizer personalizado. |
filtro_char | Especifica o filtro de caracteres a ser utilizado, que pode ser embutido ou customizado. O que é recebido aqui é um array. |
filtro | Especifica o termo filtro a ser utilizado, que pode ser embutido ou customizado. O que é recebido aqui é um array. |
A seguir explicaremos cada configuração através de exemplos.
// PUT http://localhost:9200/custom-analyzer-test
// body内容
{
"settings": {
"analysis": {
"analyzer": {
// 当前索引中定义的分析器
"my_analyzer": {
// 自定义的分析器名称
"type":"custom", // 类型-自定义分析器
"tokenizer": "my_tokenizer", // 自己定义的分词器
"char_filter": ["&_to_and"], // 自定义的分析器使用的字符过滤器集合
"filter":["my_stopwords","lowercase"] // 自定义的分析器使用的词项过滤器集合
}
},
"char_filter": {
// 当前索引中的字符过滤器集合
"&_to_and": {
// 自定义字符过滤器的名称
"type": "mapping", // 字符过滤器类型为mapping
"mappings":["& => and"]
}
},
"tokenizer":{
// 当前索引中定义的分词器
"my_tokenizer":{
"type":"pattern",
"pattern":","
}
},
"filter":{
// 当前索引中定义的词项过滤器
"my_stopwords":{
"type":"stop",
"stopwords": [ "the","a"]
}
}
}
}
}
Teste um analisador personalizado
// GET http://localhost:9200/custom-analyzer-test/_analyze
// body内容
{
"text":"I,Like & StEak,the,和西红柿,2333 !",
"analyzer":"my_analyzer"
}
O resultado é o seguinte:
O diagrama de fluxo de trabalho deste analisador personalizado é mostrado na figura abaixo.
5.7 analisador chinês
5.7.1 Suporte de análise do Elasticsearch para chinês
No analisador fornecido pelo Elasticsearch, o suporte ao chinês não é amigável o suficiente, não reconhece automaticamente frases em chinês, como: estudo, escola, etc.
Por exemplo, use o analisador padrão para analisar “Vou para a escola estudar”.
// GET http://localhost:9200/_analyze
// body内容
{
"text":"我要去学校学习",
"analyzer":"standard"
}
O resultado é o seguinte:
Pode-se observar pelos resultados acima que o uso do analisador fornecido pelo Elasticsearch não pode atender às nossas necessidades de segmentação de palavras chinesas.
Portanto, costumamos usar o tokenizer IK para expansão.
5.7.2 Introdução ao segmentador de palavras IK
O segmentador de palavras IK é um segmentador de palavras Java gratuito e de código aberto. É um dos segmentadores de palavras chineses mais populares atualmente. É simples e estável, mas se você deseja resultados particularmente bons, precisa manter seu próprio dicionário de sinônimos e oferecer suporte personalizado dicionários.
5.7.3 Instalação do segmentador de palavras IK
-
Link para Download
https://github.com/medcl/elasticsearch-análise-ik
Observação: você deve escolher o segmentador de palavras ik correspondente à sua versão do Elasticsearch.
-
implantar
Descompacte o segmentador de palavras IK baixado no subdiretório plugins do diretório de instalação do Elasticsearch.
Após a descompactação, reinicie o Elasticsearch.
Nota: Se o erro for o seguinte ao iniciar:
java.lang.IllegalStateException: Could not load plugin descriptor for plugin directory [commons-codec-1.9.jar] at org.elasticsearch.plugins.PluginsService.readPluginBundle(PluginsService.java:403) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.plugins.PluginsService.findBundles(PluginsService.java:388) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.plugins.PluginsService.getPluginBundles(PluginsService.java:381) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.plugins.PluginsService.<init>(PluginsService.java:152) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.node.Node.<init>(Node.java:317) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.node.Node.<init>(Node.java:266) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Bootstrap$5.<init>(Bootstrap.java:227) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:227) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:393) [elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:170) [elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:161) [elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86) [elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:127) [elasticsearch-cli-7.8.0.jar:7.8.0] at org.elasticsearch.cli.Command.main(Command.java:90) [elasticsearch-cli-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:126) [elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:92) [elasticsearch-7.8.0.jar:7.8.0] Caused by: java.nio.file.NoSuchFileException: D:\Software\Work\elasticsearch-7.8.0\plugins\commons-codec-1.9.jar\plugin-descriptor.properties at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79) ~[?:?] at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97) ~[?:?] at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102) ~[?:?] at sun.nio.fs.WindowsFileSystemProvider.newByteChannel(WindowsFileSystemProvider.java:230) ~[?:?] at java.nio.file.Files.newByteChannel(Files.java:361) ~[?:1.8.0_91] at java.nio.file.Files.newByteChannel(Files.java:407) ~[?:1.8.0_91] at java.nio.file.spi.FileSystemProvider.newInputStream(FileSystemProvider.java:384) ~[?:1.8.0_91] at java.nio.file.Files.newInputStream(Files.java:152) ~[?:1.8.0_91] at org.elasticsearch.plugins.PluginInfo.readFromProperties(PluginInfo.java:156) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.plugins.PluginsService.readPluginBundle(PluginsService.java:400) ~[elasticsearch-7.8.0.jar:7.8.0] ... 15 more [2023-04-18T17:23:45,388][ERROR][o.e.b.ElasticsearchUncaughtExceptionHandler] [LAPTOP-AN1JMLBC] uncaught exception in thread [main] org.elasticsearch.bootstrap.StartupException: java.lang.IllegalStateException: Could not load plugin descriptor for plugin directory [commons-codec-1.9.jar] at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:174) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:161) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:127) ~[elasticsearch-cli-7.8.0.jar:7.8.0] at org.elasticsearch.cli.Command.main(Command.java:90) ~[elasticsearch-cli-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:126) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:92) ~[elasticsearch-7.8.0.jar:7.8.0] Caused by: java.lang.IllegalStateException: Could not load plugin descriptor for plugin directory [commons-codec-1.9.jar] at org.elasticsearch.plugins.PluginsService.readPluginBundle(PluginsService.java:403) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.plugins.PluginsService.findBundles(PluginsService.java:388) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.plugins.PluginsService.getPluginBundles(PluginsService.java:381) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.plugins.PluginsService.<init>(PluginsService.java:152) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.node.Node.<init>(Node.java:317) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.node.Node.<init>(Node.java:266) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Bootstrap$5.<init>(Bootstrap.java:227) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:227) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:393) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:170) ~[elasticsearch-7.8.0.jar:7.8.0] ... 6 more Caused by: java.nio.file.NoSuchFileException: D:\Software\Work\elasticsearch-7.8.0\plugins\commons-codec-1.9.jar\plugin-descriptor.properties at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79) ~[?:?] at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97) ~[?:?] at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102) ~[?:?] at sun.nio.fs.WindowsFileSystemProvider.newByteChannel(WindowsFileSystemProvider.java:230) ~[?:?] at java.nio.file.Files.newByteChannel(Files.java:361) ~[?:1.8.0_91] at java.nio.file.Files.newByteChannel(Files.java:407) ~[?:1.8.0_91] at java.nio.file.spi.FileSystemProvider.newInputStream(FileSystemProvider.java:384) ~[?:1.8.0_91] at java.nio.file.Files.newInputStream(Files.java:152) ~[?:1.8.0_91] at org.elasticsearch.plugins.PluginInfo.readFromProperties(PluginInfo.java:156) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.plugins.PluginsService.readPluginBundle(PluginsService.java:400) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.plugins.PluginsService.findBundles(PluginsService.java:388) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.plugins.PluginsService.getPluginBundles(PluginsService.java:381) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.plugins.PluginsService.<init>(PluginsService.java:152) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.node.Node.<init>(Node.java:317) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.node.Node.<init>(Node.java:266) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Bootstrap$5.<init>(Bootstrap.java:227) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:227) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:393) ~[elasticsearch-7.8.0.jar:7.8.0] at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:170) ~[elasticsearch-7.8.0.jar:7.8.0] ... 6 more
Você pode criar um subdiretório ik em plugins e então colocar os arquivos descompactados no subdiretório ik.
5.7.4 Explicação da configuração do segmentador de palavras IK
No diretório de configuração do segmentador de palavras ik, existem algumas configurações que vêm com o segmentador de palavras ik.
O significado de cada configuração é mostrado na tabela a seguir
Nome do arquivo de configuração | significado |
---|---|
principal.dic | léxico principal |
preposição.dic | Partículas modais (também, e, mas, etc.) |
stopword.dic | Palavras de parada em inglês |
quantificador.dic | palavra de unidade de medida |
sufixo.dic | Palavras de sufixo (província, cidade, instituto, etc.) |
sobrenome.dic | Dicionário de Cem Sobrenomes de Família |
extra_main.dic | Vocabulário principal estendido |
extra_single_word.dic、extra_single_word_full.dic、extra_single_word_low_freq.dic | Biblioteca de palavras expandida |
extra_stopword.dic | Vocabulário de parada estendido |
IKAnalyzer.cfg.xml | Arquivo de configuração do tokenizador IK |
5.7.5 Analisador integrado do tokenizador IK
Existem dois analisadores integrados ao segmentador de palavras IK: ik_max_word e ik_smart
-
i_max_word
Divida o texto na granularidade mais fina
-
eu_inteligente
Divida o texto na granularidade mais grosseira
-
Compare os dois analisadores com exemplos
i_max_word
// GET http://localhost:9200/_analyze // body内容 { "text":"我要去学校学习", "analyzer":"ik_max_word" }
O resultado é o seguinte:
eu_inteligente
// GET http://localhost:9200/_analyze // body内容 { "text":"我要去学校学习", "analyzer":"ik_smart" }
O resultado é o seguinte:
5.7.6 Frase expandida com segmentador de palavras IK
Quando precisamos fazer com que certas palavras formem uma frase específica, podemos expandir a frase personalizada expandindo a frase.
Por exemplo, “League of Legends” não é uma frase específica em si, ela será dividida pelo tokenizer.
Vamos testar abaixo
// GET http://localhost:9200/_analyze
// body内容
{
"text":"英雄联盟",
"analyzer":"ik_smart"
}
O resultado é o seguinte:
Como você pode ver, "League of Legends" será dividido em duas palavras: "Heroes" e "League". Não é isso que queremos. Queremos que "League of Legends" seja tratado como um único termo.
Neste momento, podemos configurá-lo no arquivo IKAnalyzer.cfg.xml no diretório de configuração do segmentador de palavras ik.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict"></entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
</properties>
Fazemos a seguinte configuração
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">mydic.dic</entry>
</properties>
Crie o arquivo mydic.dic no diretório de configuração, escreva “League of Legends” no arquivo e reinicie o Elasticsearch.
Em seguida, testamos novamente
// GET http://localhost:9200/_analyze
// body内容
{
"text":"英雄联盟",
"analyzer":"ik_smart"
}
O resultado é o seguinte:
Como você pode ver, “League of Legends” é tratado como um termo e não será dividido.
referência