Introduction rapide à la recherche en texte intégral avec ElasticSearch

Introduction rapide à la recherche en texte intégral avec ElasticSearch

1. Vue d'ensemble

Requêtes de recherche en texte intégral et recherches linguistiques sur des documents. Il comprend un ou plusieurs mots ou expressions et renvoie les documents correspondant aux conditions de recherche.

ElasticSearch est un moteur de recherche basé surApache Lucene, une bibliothèque de logiciels gratuits et open source de recherche d'informations. Il fournit un moteur de recherche en texte intégral distribué avec une interface Web HTTP et des documents JSON sans schéma.

Cet article examine l'API ElasticSearch REST et présente les opérations de base utilisant uniquement des requêtes HTTP.

2. Installer

Pour installer ElasticSearch sur votre machine, veuillez vous référer auxofficial setup guide.

L'API RESTful s'exécute sur le port 9200. Laissez-nous tester s'il fonctionne correctement en utilisant la commande curl suivante:

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

Si vous observez la réponse suivante, l'instance s'exécute correctement:

{
  "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. Indexation de documents

ElasticSearch est orienté document. Il stocke et indexe les documents. L'indexation crée ou met à jour des documents. Après l’indexation, vous pouvez rechercher, trier et filtrer des documents complets, et non des lignes de données en colonnes. Il s’agit d’une façon fondamentalement différente de penser les données et est l’une des raisons pour lesquelles ElasticSearch peut effectuer une recherche complexe en texte intégral.

Les documents sont représentés sous forme d'objets JSON. La sérialisation JSON est supportée par la plupart des langages de programmation et est devenue le format standard utilisé par le mouvement NoSQL. C'est simple, concis et facile à lire.

Nous allons utiliser les entrées aléatoires suivantes pour effectuer notre recherche en texte intégral:

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

Avant de pouvoir indexer un document, nous devons décider où le stocker. Il est possible d’avoir plusieurs index, qui à leur tour contiennent plusieurs types. Ces types contiennent plusieurs documents et chaque document comporte plusieurs champs.

Nous allons stocker nos documents en utilisant le schéma suivant:

text: le nom de l'index. article: le nom du type. id: l'ID de cet exemple d'entrée de texte particulier.

Pour ajouter un document, nous allons exécuter la commande suivante:

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."
}'

Ici, nous utilisonsid=1, nous pouvons ajouter d'autres entrées en utilisant la même commande et un id incrémenté.

4. Récupération de documents

Après avoir ajouté tous nos documents, nous pouvons vérifier le nombre de documents à l'aide de la commande suivante dans le cluster:

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

De plus, nous pouvons obtenir un document en utilisant son identifiant avec la commande suivante:

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

Et nous devrions obtenir la réponse suivante de la recherche élastique:

{
  "_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."
  }
}

Comme on peut le voir, cette réponse correspond à l’entrée ajoutée à l’aide de l’id 1.

5. Interroger des documents

OK, effectuons une recherche en texte intégral avec la commande suivante:

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

Et nous obtenons le résultat suivant:

{
  "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."
        }
      }
    ]
  }
}

Comme nous pouvons le voir, nous recherchons“him departure” et nous obtenons deux résultats avec des scores différents. Le premier résultat est évident car le texte contient la recherche effectuée et comme nous pouvons le voir, nous avons le score de1.4513469.

Le deuxième résultat est récupéré car le document cible contient le mot «lui».

Par défaut, ElasticSearch trie les résultats de correspondance en fonction de leur pertinence, c'est-à-dire de la correspondance entre chaque document et la requête. Notez que le score du deuxième résultat est petit par rapport au premier résultat, ce qui indique une pertinence moindre.

La correspondance floue traite deux mots «similaires» comme s'ils étaient le même mot. Premièrement, nous devons définir ce que nous entendons par flou.

Elasticsearch prend en charge une distance d'édition maximale, spécifiée avec le paramètre de flou, de 2. Le paramètre de flou peut être réglé sur AUTO, ce qui entraîne les distances d'édition maximales suivantes:

  • 0 pour les chaînes d'un ou deux caractères

  • 1 pour les chaînes de trois, quatre ou cinq caractères

  • 2 pour les chaînes de plus de cinq caractères

vous constaterez peut-être qu’une distance d’édition de2 renvoie des résultats qui ne semblent pas liés.

Vous pouvez obtenir de meilleurs résultats et de meilleures performances avec un flou maximal de 1. La distance fait référence à la distance de Levenshtein qui est une métrique de chaîne pour mesurer la différence entre deux séquences. De manière informelle, leLevenshtein distance entre deux mots est le nombre minimum de modifications à un seul caractère.

OK, effectuons notre recherche avec flou:

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

Et voici le résultat:

{
  "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."
        }
      }
    ]
  }
}'

Comme nous pouvons le voir, le flou nous donne plus de résultats.

Nous devons utiliser le flou avec précaution, car il a tendance à extraire des résultats qui ne semblent pas liés.

7. Conclusion

Dans ce rapide tutoriel, nous nous sommes concentrés surindexing documents and querying Elasticsearch for full-text search, directly via it’s REST API.

Bien sûr, nous avons des API disponibles pour plusieurs langages de programmation lorsque nous en avons besoin - mais l’API est toujours très pratique et n’est pas agnostique.