Skip to content

nosql-bootcamp/elasticsearch-102

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 

Repository files navigation

ElasticSearch 102

elastic-logo

ElasticSearch 102 est un workshop permettant de découvrir le driver Node.js pour ElasticSearch.

Creative Commons Licence

elasticsearch-102 par Benjamin CAVY et Sébastien PRUNIER est distribué sous les termes de la licence Creative Commons - Attribution - NonCommercial - ShareAlike.

Pré requis

Nous considérons que vous avez déjà réalisé les workshops suivants :

Vous allez également avoir besoin de Node.js. Si ce n'est pas déjà fait, installez node et npm sur votre machine.

Vérifiez les versions installées de node (minimum v10.x) et npm (minimum v6.x) :

node -v
v10.16.0
npm -v
6.9.0

Le jeu de données

Le jeu de données utilisé pour le workshop est un ensemble d'actrices et d'acteurs, issus de la base IMDb.

Plus précisément, deux fichiers nous servent de source de données :

  • Top_1000_Actors_and_Actresses.csv est un fichier CSV contenant le Top 1000 des actrices et acteurs, depuis lequel nous pourrons extraire le nom de l'actrice ou de l'acteur, sa date de naissance et son identifiant IMDb.
  • Top_1000_Actors_and_Actresses.json est un fichier contenant une fiche détaillée au format JSON de chacun des 1000 actrices et acteur. Nous pourrons extraire de ce fichier une description, un lien vers une photos et une liste de métiers (acteur, réalisateur, producteur, etc...)

Ces deux fichiers sont disponibles dans le dossier src/data.

Driver natif ElasticSearch pour Node.js

Les exemples de code du workshop se basent sur le driver natif ElasticSearch pour Node.js. La version utilisée est la version 7.11.0.

L'avantage d'utiliser Node.js et le driver natif est que la syntaxe des requêtes du driver est quasiment identique à celles effectuées dans le shell.

La dépendance au driver elasticsearch est déjà présente dans le fichier package.json, ainsi que la dépendance au module csv-parser nécessaire pour la suite :

"dependencies": {
  "@elastic/elasticsearch": "^7.5.0",
  "csv-parser": "^2.3.2"
}

Création des acteurs

L'objectif de cette première partie est d'alimenter un index imdb à partir du fichier CSV Top_1000_Actors_and_Actresses.csv.

Pour cela nous nous appuyons sur le module csv-parser pour lire le fichier CSV et sur l'api bulk d'elasticsearch, qui va permettre l'insertion de tous les documents en un seul appel :

const csv = require('csv-parser');
const fs = require('fs');
const { Client } = require('@elastic/elasticsearch');

const client = new Client({ node: 'http://localhost:9200' });

// Création de l'indice
client.indices.create({ index: 'imdb' }, (err, resp) => {
  if (err) console.trace(err.message);
});

let actors = [];
fs
  .createReadStream('./data/Top_1000_Actors_and_Actresses.csv')
  .pipe(csv())
  // Pour chaque ligne on créé un document JSON pour l'acteur correspondant
  .on('data', data => {
    actors.push({
      imdb_id: data.imdb_id,
      name: data.name,
      birth_date: data.birth_date
    });
  })
  // A la fin on créé l'ensemble des acteurs dans ElasticSearch
  .on('end', () => {
    client.bulk(createBulkInsertQuery(actors), (err, resp) => {
      if (err) console.trace(err.message);
      else console.log(`Inserted ${resp.body.items.length} actors`);
      client.close();
    });
  });

// Fonction utilitaire permettant de formatter les données pour l'insertion "bulk" dans elastic
function createBulkInsertQuery(actors) {
  const body = actors.reduce((acc, actor) => {
    const { name, birth_date } = actor;
    acc.push({ index: { _index: 'imdb', _type: '_doc', _id: actor.imdb_id } })
    acc.push({ name, birth_date })
    return acc
  }, []);

  return { body };
}

Ce code est disponible dans le fichier src/insert_actors.js. Vous pouvez l'exécuter afin d'alimenter une première fois la base :

cd src

# A ne lancer qu'une seule fois pour récupérer les dépendances
npm install

node insert_actors.js

Mise à jour des acteurs

L'objectif de cette seconde partie est de compléter chaque document de la collection actors à partir des données du fichier Top_1000_Actors_and_Actresses.json.

Pour cela, nous nous appuyons à nouveau sur l'api bulk.

const fs = require('fs');
const { Client } = require('@elastic/elasticsearch');

const client = new Client({ node: 'http://localhost:9200' });

fs.readFile(
  './data/Top_1000_Actors_and_Actresses.json',
  'utf8',
  (err, data) => {
    const actorsToUpdate = data
      .split('\n')
      // Chaque ligne correspond à un document JSON décrivant un acteur en détail
      .map(line => JSON.parse(line))
      // On transforme chaque ligne en requête de mise à jour qui sera utilisée dans un 'bulkWrite()'
      .map(actor => actor.data);

    client.bulk(createBulkUpdateQuery(actorsToUpdate), (err, resp) => {
      if (err) console.trace(err.message);
      else console.log(`Updated ${resp.body.items.length} actors`);
      client.close();
    });
  }
);

function createBulkUpdateQuery(actors) {
  const body = actors.reduce((acc, actor) => {
    const {
      description = 'No description provided',
      image,
      occupation
    } = actor;
    acc.push({ update: { _index: 'imdb', _type: '_doc', _id: actor.id } })
    acc.push({
      doc: {
        description: description.replace(
          '                                See full bio »',
          ''
        ),
        image,
        occupation
      }
    })

    return acc
  }, []);

  return { body };
}

Ce code est disponible dans le fichier src/update_actors.js. Vous pouvez l'exécuter :

cd src

# A ne lancer qu'une seule fois pour récupérer les dépendances
npm install

node update_actors.js

Requêtes

A vous de jouer pour exécuter quelques requêtes intéressantes sur les données !

Par exemple pour récupérer l'acteur le plus vieux du Top 1000 :

client
  .search({
    index: 'imdb',
    body: {
      size: 1,
      sort: [{ birth_date: 'asc' }]
    }
  })
  .then(resp => console.log(resp.body.hits.hits[0]._source.name));

Autre exemple pour compter le nombre d'acteurs qui sont aussi des producteurs :

client
  .count({
    index: 'imdb',
    body: {
      query: {
        term: {
          occupation: {
            value: 'producer'
          }
        }
      }
    }
  })
  .then(resp => {
    console.log(resp.body.count);
  });

About

Prise en main du driver natif Node.js pour Elasticsearch

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •