Elasticsearch é un buscador con API json rest, que utiliza Lucene e está escrito en Java. Unha descrición de todas as vantaxes deste motor está dispoñible en sitio web oficial. No que segue faremos referencia a Elasticsearch como ES.
Úsanse motores similares para buscas complexas nunha base de datos de documentos. Por exemplo, buscar tendo en conta a morfoloxía da lingua ou buscar por xeocoordenadas.
Neste artigo falarei dos conceptos básicos de ES usando o exemplo de indexación de publicacións de blog. Vouche mostrar como filtrar, ordenar e buscar documentos.
Para non depender do sistema operativo, farei todas as solicitudes a ES usando CURL. Tamén hai un complemento para google chrome chamado sentido.
O texto contén ligazóns a documentación e outras fontes. Ao final hai ligazóns para acceder rapidamente á documentación. As definicións de termos descoñecidos pódense atopar en glosarios.
Instalación de ES
Para iso, primeiro necesitamos Java. Desenvolvedores recomendo instalar versións de Java máis recentes que a actualización 8 de Java 20 ou a actualización 7 de Java 55.
# Добавим документ c id 1 типа post в индекс blog.
# ?pretty указывает, что вывод должен быть человеко-читаемым.
curl -XPUT "$ES_URL/blog/post/1?pretty" -d'
{
"title": "Веселые котята",
"content": "<p>Смешная история про котят<p>",
"tags": [
"котята",
"смешная история"
],
"published_at": "2014-09-12T20:44:42+00:00"
}'
ES creado automaticamente índice blog e тип publicación. Podemos debuxar unha analoxía condicional: un índice é unha base de datos e un tipo é unha táboa nesta base de datos. Cada tipo ten o seu propio esquema − mapeamento, igual que unha táboa relacional. A asignación xérase automaticamente cando se indexa o documento:
# Получим mapping всех типов индекса blog
curl -XGET "$ES_URL/blog/_mapping?pretty"
Na resposta do servidor, engadín os valores dos campos do documento indexado nos comentarios:
Paga a pena notar que ES non diferencia entre un único valor e unha matriz de valores. Por exemplo, o campo de título simplemente contén un título e o campo de etiquetas contén unha matriz de cadeas, aínda que se representan do mesmo xeito na asignación.
Máis adiante falaremos sobre a cartografía.
Solicitudes
Recuperando un documento polo seu ID:
# извлечем документ с id 1 типа post из индекса blog
curl -XGET "$ES_URL/blog/post/1?pretty"
Apareceron novas claves na resposta: _version и _source. En xeral, todas as claves comezan por _ están clasificados como oficiais.
Clave _version mostra a versión do documento. É necesario para que funcione o mecanismo de bloqueo optimista. Por exemplo, queremos cambiar un documento que ten a versión 1. Enviamos o documento modificado e indicamos que se trata dunha edición dun documento coa versión 1. Se alguén tamén editou un documento coa versión 1 e enviou cambios antes que nós, entón ES non aceptará os nosos cambios, porque almacena o documento coa versión 2.
Clave _source contén o documento que indexamos. ES non usa este valor para operacións de busca porque Os índices úsanse para buscar. Para aforrar espazo, ES almacena un documento de orixe comprimido. Se só necesitamos o identificador e non o documento de orixe completo, entón podemos desactivar o almacenamento de orixe.
Se non necesitamos información adicional, só podemos obter o contido de _source:
curl -XPUT "$ES_URL/blog/post/3" -d'
{
"title": "Как у меня появился котенок",
"content": "<p>Душераздирающая история про бедного котенка с улицы<p>",
"tags": [
"котята"
],
"published_at": "2014-07-21T20:44:42+00:00"
}'
Ordenación
# найдем последний пост по дате публикации и извлечем поля title и published_at
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"size": 1,
"_source": ["title", "published_at"],
"sort": [{"published_at": "desc"}]
}'
Escollemos o último post. size limita o número de documentos a emitir. total mostra o número total de documentos correspondentes á solicitude. sort na saída contén unha matriz de enteiros polos que se realiza a ordenación. Eses. a data converteuse nun número enteiro. Pódese atopar máis información sobre a clasificación en documentación.
Filtros e consultas
ES desde a versión 2 non distingue entre filtros e consultas introdúcese o concepto de contextos.
Un contexto de consulta difire dun contexto de filtro en que a consulta xera un _score e non se almacena na memoria caché. Vouche mostrar cal é o _score máis tarde.
Filtrar por data
Usamos a solicitude alcance no contexto do filtro:
# получим посты, опубликованные 1ого сентября или позже
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"filter": {
"range": {
"published_at": { "gte": "2014-09-01" }
}
}
}'
Filtrar por etiquetas
Usamos consulta de termos para buscar ID de documentos que conteñan unha palabra determinada:
# найдем все документы, в поле tags которых есть элемент 'котята'
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"_source": [
"title",
"tags"
],
"filter": {
"term": {
"tags": "котята"
}
}
}'
Non obstante, se buscamos "historias" no campo de contido, non atoparemos nada, porque O índice contén só as palabras orixinais, non as súas raíces. Para facer unha busca de alta calidade, cómpre configurar o analizador.
Campo _score espectáculos relevancia. Se a solicitude se executa nun contexto de filtro, entón o valor _score sempre será igual a 1, o que significa unha coincidencia completa co filtro.
Analizadores
Analizadores son necesarios para converter o texto fonte nun conxunto de fichas.
Os analizadores consisten nun Tokenizador e varias opcionais TokenFilters. Tokenizer pode ir precedido de varios CharFilters. Os tokenizadores dividen a cadea de orixe en tokens, como espazos e caracteres de puntuación. TokenFilter pode cambiar tokens, eliminar ou engadir novos, por exemplo, deixar só o tallo da palabra, eliminar preposicións, engadir sinónimos. CharFilter: cambia toda a cadea de orixe, por exemplo, elimina as etiquetas html.
Aproveitemos api e vexamos como os analizadores estándar e ruso transforman a cadea "Historias divertidas sobre gatiños":
# используем анализатор standard
# обязательно нужно перекодировать не ASCII символы
curl -XGET "$ES_URL/_analyze?pretty&analyzer=standard&text=%D0%92%D0%B5%D1%81%D0%B5%D0%BB%D1%8B%D0%B5%20%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D0%B8%20%D0%BF%D1%80%D0%BE%20%D0%BA%D0%BE%D1%82%D1%8F%D1%82"
O analizador estándar dividiu a cadea por espazos e converteu todo a minúsculas, o analizador ruso eliminou as palabras sen importancia, converteuno en minúsculas e deixou o tronco das palabras.
Vexamos que Tokenizer, TokenFilters, CharFilters usa o analizador ruso:
Imos describir o noso analizador baseado en ruso, que eliminará as etiquetas html. Chamémoslle por defecto, porque un analizador con este nome empregarase por defecto.
En primeiro lugar, todas as etiquetas HTML eliminaranse da cadea de orixe, despois o estándar do tokenizer dividirao en tokens, os tokens resultantes moveranse a minúsculas, as palabras insignificantes eliminaranse e os tokens restantes seguirán sendo a raíz da palabra.
Creando un índice
Arriba describimos o analizador predeterminado. Aplicarase a todos os campos de cadea. A nosa publicación contén unha serie de etiquetas, polo que as etiquetas tamén serán procesadas polo analizador. Porque Buscamos publicacións por coincidencia exacta cunha etiqueta, entón necesitamos desactivar a análise para o campo de etiquetas.
Imos crear un índice blog2 cun analizador e mapeo, no que a análise do campo de etiquetas está desactivada:
Imos engadir as mesmas 3 publicacións a este índice (blog2). Omitirei este proceso porque... é semellante a engadir documentos ao índice do blog.
Busca de texto completo con soporte de expresión
Vexamos outro tipo de solicitudes:
# найдем документы, в которых встречается слово 'истории'
# query -> simple_query_string -> query содержит поисковый запрос
# поле title имеет приоритет 3
# поле tags имеет приоритет 2
# поле content имеет приоритет 1
# приоритет используется при ранжировании результатов
curl -XPOST "$ES_URL/blog2/post/_search?pretty" -d'
{
"query": {
"simple_query_string": {
"query": "истории",
"fields": [
"title^3",
"tags^2",
"content"
]
}
}
}'
Porque Estamos a usar un analizador con derivación rusa, entón esta solicitude devolverá todos os documentos, aínda que só conteñen a palabra "historia".
A solicitude pode conter caracteres especiais, por exemplo:
""fried eggs" +(eggplant | potato) -frittata"
Sintaxe de solicitude:
+ signifies AND operation
| signifies OR operation
- negates a single token
" wraps a number of tokens to signify a phrase for searching
* at the end of a term signifies a prefix query
( and ) signify precedence
~N after a word signifies edit distance (fuzziness)
~N after a phrase signifies slop amount
# найдем документы без слова 'щенки'
curl -XPOST "$ES_URL/blog2/post/_search?pretty" -d'
{
"query": {
"simple_query_string": {
"query": "-щенки",
"fields": [
"title^3",
"tags^2",
"content"
]
}
}
}'
# получим 2 поста про котиков
Se estás interesado en artigos-leccións similares, tes ideas para novos artigos ou tes propostas de cooperación, estarei encantado de recibir unha mensaxe nunha mensaxe persoal ou por correo electrónico [protexido por correo electrónico].