Insert/Suppression massif de données sur Elasticsearch avec jq

Elasticsearch (ES), est l’une des bases de données de référence pour faire de la recherche par texte (full text search) ou par facettes. La technologie est basée initialement sur Apache Lucene et propose notamment une API REST très bien documentée. Cependant, il n’est pas forcément aisé de réaliser des opéations de suppression ou update de masse comme cela peut être le cas sur des bases de données SQL traditionnelles telles que MySQL ou PostgreSQL. Il existe par exemple un plugin SQL ou une API ‘Delete by query’ qui peuvent être des alternatives intéressantes mais qui ne marcheront pas sur les anciennes versions d’Elasticsearch.

Dans ce tutorial, nous n’utiliserons que l’API BulkES 1.x or ES 2.x et les lignes de commandes.

BULK INSERT

Voyons tout d’abord comment faire un bulk insert, conformément à la documentation ES 1.x or ES 2.x

curl -XPOST 'localhost:9200/_bulk?pretty' -H 'Content-Type: application/json' -d'
{ "index":  { "_index": "hello", "_type": "doc" }}
{ "title": "Hello world" }
{ "index":  { "_index": "hello", "_type": "doc" }}
{ "title": "Hello world 2" }
'

Et pour récupérer les 2 documents crées:

curl -XGET 'localhost:9200/hello/_search?pretty'
> {
  "took" : 10,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "hello",
        "_type" : "doc",
        "_id" : "AVnnCn_StArLYxHTogPv",
        "_score" : 1.0,
        "_source" : {
          "title" : "Hello world"
        }
      },
      {
        "_index" : "hello",
        "_type" : "doc",
        "_id" : "AVnnCn_StArLYxHTogPw",
        "_score" : 1.0,
        "_source" : {
          "title" : "Hello world 2"
        }
      }
    ]
  }
}

JQ

La reéponse HTTP contient pas mal de metadata et n’est pas aisée à lire. L’on peut alors utiliser jq pour parser le JSON depuis le terminal.

Par exemple, pour n’avoir que les titres:

curl -XGET 'localhost:9200/hello/_search' | 
jq '.hits.hits[] | 
{title:._source.title}' -c

> {"title":"Hello world"}
{"title":"Hello world 2"}

L’option -c permet d’avoir les outpouts en une seule ligne. La réponse n’est pas un array mais bien plusieurs lignes de JSON, ce qui sera utile par la suite.

BULK CREATE, BULK DELETE

Remplaçons maintenant  ‘world’ par ‘Everyone’ et insérons les nouveaux documents dans la base de donnée:

curl -XGET 'localhost:9200/hello/_search' | 
jq '.hits.hits[] | 
{ "index":  {_index, _type, _id }}, ._source' -c | 
sed 's/world/Everyone/g' | 
curl -XPOST http://localhost:9200/_bulk --data-binary @-

Le verbe ‘create’ est utile pour insérer un document uniquement s’il n’existe pas encore dans l’index (basé sur le champs _id). Par exemple, pour copier de la donnée d’un index à un autre:

curl -XGET 'localhost:9200/hello/_search' | 
jq '.hits.hits[] | 
{ "create":  {_index:"new", _type, _id }}, ._source' -c | 
curl -XPOST http://localhost:9200/_bulk --data-binary @-

Enfin, pour faire une suppression de masse de tous les documents:

curl -XGET 'localhost:9200/hello/_search' | 
jq '.hits.hits[] | 
{ "delete":  {_index:"new", _type, _id }}' -c | 
curl -XPOST http://localhost:9200/_bulk --data-binary @-

 

En conclusion, si vous avez à faire 100 000 opérations ou plus, l’API bulk permet de le faire sans plugins et en quelques minutes seulement!

Insert/Suppression massif de données sur Elasticsearch avec jq

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *