Introdução rápida à pesquisa de texto completo com ElasticSearch

Introdução rápida à pesquisa de texto completo com ElasticSearch

1. Visão geral

A pesquisa de texto completo consulta e realiza pesquisas linguísticas em documentos. Inclui palavras ou frases únicas ou múltiplas e retorna documentos que correspondem à condição de pesquisa.

ElasticSearch é um mecanismo de busca baseado emApache Lucene, uma biblioteca de software de recuperação de informação gratuita e de código aberto. Ele fornece um mecanismo de pesquisa distribuído de texto completo com uma interface da Web HTTP e documentos JSON sem esquema.

Este artigo examina a API REST do ElasticSearch e demonstra operações básicas usando apenas solicitações HTTP.

2. Configuração

Para instalar o ElasticSearch em sua máquina, consulteofficial setup guide.

A API RESTfull é executada na porta 9200. Vamos testar se está sendo executado corretamente usando o seguinte comando curl:

curl -XGET 'http://localhost:9200/'

Se você observar a seguinte resposta, a instância está sendo executada corretamente:

{
  "name": "NaIlQWU",
  "cluster_name": "elasticsearch",
  "cluster_uuid": "enkBkWqqQrS0vp_NXmjQMQ",
  "version": {
    "number": "5.1.2",
    "build_hash": "c8c4c16",
    "build_date": "2017-01-11T20:18:39.146Z",
    "build_snapshot": false,
    "lucene_version": "6.3.0"
  },
  "tagline": "You Know, for Search"
}

3. Documentos de indexação

O ElasticSearch é orientado a documentos. Ele armazena e indexa documentos. A indexação cria ou atualiza documentos. Após a indexação, você pode pesquisar, classificar e filtrar documentos completos, não linhas de dados colunares. Essa é uma maneira fundamentalmente diferente de pensar sobre dados e é um dos motivos pelos quais o ElasticSearch pode executar uma pesquisa complexa em texto completo.

Os documentos são representados como objetos JSON. A serialização JSON é suportada pela maioria das linguagens de programação e se tornou o formato padrão usado pelo movimento NoSQL. É simples, conciso e fácil de ler.

Usaremos as seguintes entradas aleatórias para realizar nossa pesquisa de texto completo:

{
  "title": "He went",
  "random_text": "He went such dare good fact. The small own seven saved man age."
}

{
  "title": "He oppose",
  "random_text":
    "He oppose at thrown desire of no. \
      Announcing impression unaffected day his are unreserved indulgence."
}

{
  "title": "Repulsive questions",
  "random_text": "Repulsive questions contented him few extensive supported."
}

{
  "title": "Old education",
  "random_text": "Old education him departure any arranging one prevailed."
}

Antes de podermos indexar um documento, precisamos decidir onde armazená-lo. É possível ter vários índices, que por sua vez contêm vários tipos. Esses tipos contêm vários documentos e cada documento possui vários campos.

Vamos armazenar nossos documentos usando o seguinte esquema:

text: o nome do índice. article: o nome do tipo. id: O ID desta entrada de texto de exemplo particular.

Para adicionar um documento, vamos executar o seguinte comando:

curl -XPUT 'localhost:9200/text/article/1?pretty'
  -H 'Content-Type: application/json' -d '
{
  "title": "He went",
  "random_text":
    "He went such dare good fact. The small own seven saved man age."
}'

Aqui estamos usandoid=1, podemos adicionar outras entradas usando o mesmo comando e id incrementado.

4. Recuperando documentos

Depois de adicionar todos os nossos documentos, podemos verificar quantos documentos, usando o seguinte comando, temos no cluster:

curl -XGET 'http://localhost:9200/_count?pretty' -d '
{
  "query": {
    "match_all": {}
  }
}'

Além disso, podemos obter um documento usando seu ID com o seguinte comando:

curl -XGET 'localhost:9200/text/article/1?pretty'

E devemos obter a seguinte resposta da pesquisa elástica:

{
  "_index": "text",
  "_type": "article",
  "_id": "1",
  "_version": 1,
  "found": true,
  "_source": {
    "title": "He went",
    "random_text":
      "He went such dare good fact. The small own seven saved man age."
  }
}

Como podemos ver, esta resposta corresponde à entrada adicionada usando o ID 1.

5. Consultando Documentos

OK, vamos realizar uma pesquisa de texto completo com o seguinte comando:

curl -XGET 'localhost:9200/text/article/_search?pretty'
  -H 'Content-Type: application/json' -d '
{
  "query": {
    "match": {
      "random_text": "him departure"
    }
  }
}'

E obtemos o seguinte resultado:

{
  "took": 32,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 1.4513469,
    "hits": [
      {
        "_index": "text",
        "_type": "article",
        "_id": "4",
        "_score": 1.4513469,
        "_source": {
          "title": "Old education",
          "random_text": "Old education him departure any arranging one prevailed."
        }
      },
      {
        "_index": "text",
        "_type": "article",
        "_id": "3",
        "_score": 0.28582606,
        "_source": {
          "title": "Repulsive questions",
          "random_text": "Repulsive questions contented him few extensive supported."
        }
      }
    ]
  }
}

Como podemos ver, estamos procurando“him departure”e obtemos dois resultados com pontuações diferentes. O primeiro resultado é óbvio porque o texto contém a busca realizada dentro dele e como podemos ver temos a pontuação de1.4513469.

O segundo resultado é recuperado porque o documento de destino contém a palavra "ele".

Por padrão, o ElasticSearch classifica os resultados correspondentes por sua pontuação de relevância, ou seja, pela qualidade de cada documento correspondente à consulta. Observe que a pontuação do segundo resultado é pequena em relação ao primeiro hit, indicando menor relevância.

A correspondência difusa trata duas palavras que são "confusas" semelhantes como se fossem a mesma palavra. Primeiro, precisamos definir o que queremos dizer com imprecisão.

O Elasticsearch suporta uma distância máxima de edição, especificada com o parâmetro de imprecisão, 2. O parâmetro de imprecisão pode ser definido como AUTO, o que resulta nas seguintes distâncias máximas de edição:

  • 0 para strings de um ou dois caracteres

  • 1 para sequências de três, quatro ou cinco caracteres

  • 2 para sequências de mais de cinco caracteres

você pode descobrir que uma distância de edição de2 retorna resultados que não parecem estar relacionados.

Você pode obter melhores resultados e melhor desempenho com uma imprecisão máxima de 1. Distância refere-se à distância de Levenshtein, que é uma métrica de cadeia para medir a diferença entre duas seqüências. Informalmente, oLevenshtein distance entre duas palavras é o número mínimo de edições de um único caractere.

OK, vamos realizar nossa pesquisa com confusão:

curl -XGET 'localhost:9200/text/article/_search?pretty' -H 'Content-Type: application/json' -d'
{
  "query":
  {
    "match":
    {
      "random_text":
      {
        "query": "him departure",
        "fuzziness": "2"
      }
    }
  }
}'

E aqui está o resultado:

{
  "took": 88,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 4,
    "max_score": 1.5834423,
    "hits": [
      {
        "_index": "text",
        "_type": "article",
        "_id": "4",
        "_score": 1.4513469,
        "_source": {
          "title": "Old education",
          "random_text": "Old education him departure any arranging one prevailed."
        }
      },
      {
        "_index": "text",
        "_type": "article",
        "_id": "2",
        "_score": 0.41093433,
        "_source": {
          "title": "He oppose",
          "random_text":
            "He oppose at thrown desire of no.
              \ Announcing impression unaffected day his are unreserved indulgence."
        }
      },
      {
        "_index": "text",
        "_type": "article",
        "_id": "3",
        "_score": 0.2876821,
        "_source": {
          "title": "Repulsive questions",
          "random_text": "Repulsive questions contented him few extensive supported."
        }
      },
      {
        "_index": "text",
        "_type": "article",
        "_id": "1",
        "_score": 0.0,
        "_source": {
          "title": "He went",
          "random_text": "He went such dare good fact. The small own seven saved man age."
        }
      }
    ]
  }
}'

Como podemos ver, a imprecisão nos dá mais resultados.

Precisamos usar a imprecisão com cuidado, porque ela tende a recuperar resultados que parecem não relacionados.

7. Conclusão

Neste tutorial rápido nos concentramos emindexing documents and querying Elasticsearch for full-text search, directly via it’s REST API.

Obviamente, temos APIs disponíveis para várias linguagens de programação quando precisamos - mas a API ainda é bastante conveniente e independente da linguagem.