Importation en bloc d'un fichier CSV dans MongoDB à l'aide de Mongoose avec Node.js

Ce que vous allez créer

Ce sujet est vraiment agréable pour moi. Dans de nombreuses applications Web, il est assez courant d'accepter les entrées utilisateur et de sauvegarder un seul enregistrement dans votre base de données. Mais qu'en est-il lorsque vos utilisateurs (ou vous) souhaitez effectuer plusieurs insertions en une seule commande? 

Entrez cet article, qui expliquera comment créer un modèle CSV et un formulaire pour télécharger le fichier CSV, et comment analyser le fichier CSV dans un modèle Mongoose qui sera enregistré dans une base de données MongoDB..

Cet article suppose que vous avez une compréhension de base de Mongoose et de ses interactions avec MongoDB. Si vous ne le faites pas, je vous suggère de lire mon article Introduction à Mongoose pour MongoDB et Node.js en premier. Cet article décrit les interactions entre Mongoose et MongoDB en créant des schémas fortement typés à partir desquels un modèle est créé. Si vous avez déjà une bonne compréhension de Mongoose, alors poursuivons.

Commencer

Pour commencer, instancions une nouvelle application Node.js. Dans une invite de commande, accédez à l'emplacement où vous souhaitez héberger vos applications Node.js et exécutez les commandes suivantes:

mkdir csvimport cd csvimport npm init

J'ai laissé toutes les valeurs par défaut en place, mon application va donc commencer par index.js. Avant de créer et d’analyser des fichiers CSV, vous devez d’abord effectuer une première configuration. Je veux en faire une application Web; Pour ce faire, je vais utiliser le package Express afin de gérer l’ensemble de la configuration serveur nitty-gritty. Dans votre invite de commande, installez Express en exécutant la commande suivante:

npm install express --save

Étant donné que cette application Web acceptera les fichiers via un formulaire Web, je vais également utiliser le sous-package Express Express File Upload. Installons cela maintenant aussi:

npm installer express-fileupload --save

J'ai maintenant effectué suffisamment de configuration initiale pour configurer mon application Web et créer une page Web de base qui créera mon formulaire de téléchargement de fichier..

Voici mon index.js fichier qui configure mon serveur web:

var app = require ('express') (); var fileUpload = require ('express-fileupload'); var server = require ('http'). Server (app); app.use (fileUpload ()); server.listen (80); app.get ('/', fonction (req, res) res.sendFile (__ dirname + '/index.html'););

Cet exemple importe les bibliothèques Express et Express File Upload, configure mon application Web pour utiliser le téléchargement de fichier et écoute sur le port 80. Cet exemple a également créé un itinéraire utilisant Express à "/", qui sera la page d'arrivée par défaut de mon site Web. application. Cet itinéraire renvoie un index.html fichier contenant le formulaire Web qui permettra à un utilisateur de télécharger un fichier CSV. Dans mon cas, je cours sur mon ordinateur local. Ainsi, lors de ma visite à http: // localhost, je verrai le formulaire que je crée dans l'exemple suivant..

Voici mon index.html page qui crée mon formulaire pour le téléchargement d'un fichier CSV:

   Télécharger des auteurs   

Utilisez le formulaire ci-dessous pour télécharger une liste d'auteurs. Cliquez ici pour un exemple de modèle.



Ce fichier HTML contient deux choses importantes:

  1. Un lien vers "/ modèle" qui, lorsque vous cliquez dessus, téléchargera un modèle CSV pouvant être rempli avec les informations à importer.
  2. Un formulaire avec le encType définir comme multipart / form-data et un champ de saisie avec un type de fichier qui accepte les fichiers avec une extension "csv".

Comme vous l'avez peut-être remarqué, le code HTML fait référence à un modèle d'auteur. Si vous lisez mon article Introduction to Mongoose, j'ai créé un schéma d'auteur. Dans cet article, je vais recréer ce schéma et permettre à l'utilisateur d'importer en bloc une collection d'auteurs dans ma base de données MongoDB. Jetons un coup d'oeil au schéma d'auteur. Avant de faire cela, cependant, vous l’avez probablement deviné: nous devons installer le paquet Mongoose:

npm install mongoose --save

Création du schéma et du modèle

Avec Mongoose installé, créons un nouveau author.js fichier qui définira le schéma et le modèle de l'auteur:

var mangouste = require ('mangouste'); var authorSchema = mongoose.Schema (_id: mongoose.Schema.Types.ObjectId, nom: prénom: type: chaîne, obligatoire: true, nom: chaîne, biographie: chaîne, twitter: type: chaîne, valider : validator: function (text) if (text! == null && text.length> 0) renvoie text.indexOf ('https://twitter.com/') === 0; renvoie true;, message : "Le pseudo Twitter doit commencer par https://twitter.com/ ', facebook: type: Chaîne, valider: validateur: fonction (texte) if (text! == null && text.length> 0) return text.indexOf ('https://www.facebook.com/') === 0; return true;, message: 'La page Facebook doit commencer par https://www.facebook.com/', linkedin: type: String, validate: validator: function (text) if (text! == null && text.length> 0) renvoie text.indexOf ('https://www.linkedin.com/') = == 0; return true;, message: "LinkedIn doit commencer par https://www.linkedin.com/ ', profilePicture: Buffer, créé: type: Date, par défaut: Date.now); var Author = mongoose.model ('Auteur', authorSchema); module.exports = Auteur;

Avec le schéma et le modèle d'auteur créés, changeons de sujet et concentrons-nous sur la création du modèle CSV pouvant être téléchargé en cliquant sur le lien du modèle. Pour aider à la génération de modèles CSV, je vais utiliser le package JSON à CSV. Installons ça maintenant:

npm installer json2csv --save

Je vais maintenant mettre à jour mon précédent créé index.js fichier pour inclure une nouvelle route pour "/ template":

var template = require ('./ template.js'); app.get ('/ template', template.get);

J'ai seulement inclus le nouveau code pour le modèle de route ajouté au précédent index.js fichier.

La première chose que ce code fait est d’inclure un nouveau template.js fichier (à créer ensuite) et créez un itinéraire pour "/ template". Cette route appellera un obtenir fonctionner dans le template.js fichier.

Avec le serveur Express mis à jour pour inclure le nouvel itinéraire, créons le nouveau template.js fichier:

var json2csv = require ('json2csv'); exports.get = fonction (req, res) var champs = ['name.firstName', 'name.lastName', 'biographie', 'twitter', 'facebook', 'linkedin']; var csv = json2csv (data: ", fields: fields); res.set (" Content-Disposition "," pièce jointe; nomfichier = authors.csv "); res.set (" Content-Type "," application / octet-stream "); res.send (csv);;

Ce fichier comprend d’abord le fichier précédemment installé. json2csv paquet. Je crée et exporte ensuite un obtenir une fonction. Cette fonction accepte les objets requête et réponse du serveur Express..

Dans la fonction, j'ai créé un tableau des champs que je souhaite inclure dans mon modèle CSV. Cela peut être fait de deux manières. La première méthode (dans cet exemple) consiste à créer une liste statique des champs à inclure dans le modèle. La deuxième méthode consiste à créer de manière dynamique la liste des champs en extrayant les propriétés du schéma d’auteur..

La deuxième façon pourrait être faite avec le code suivant:

champs var = Object.keys (Author.schema.obj);

J'aurais aimé utiliser cette méthode dynamique, mais cela devient un peu compliqué lorsque je ne souhaite pas inclure plusieurs propriétés du schéma vers mon modèle CSV. Dans ce cas, mon modèle n'inclut pas le _id et créé propriétés car elles seront renseignées via le code. Toutefois, si vous ne souhaitez pas exclure de champs, la méthode dynamique fonctionnera également..

Création du modèle CSV

Avec le tableau de champs défini, j’utilise le json2csv package pour créer mon modèle CSV à partir de mon objet JavaScript. Ce CSV objet sera les résultats de cette route.

Et enfin, en utilisant le res propriété du serveur Express, j’ai défini deux propriétés d’en-tête qui forceront le téléchargement d’un fichier. auteurs.csv fichier.

À ce stade, si vous devez exécuter votre application Node et accéder à http: // localhost dans votre navigateur Web, le formulaire Web sera affiché avec un lien pour télécharger le modèle. En cliquant sur le lien pour télécharger le modèle, vous pourrez télécharger le auteurs.csv fichier à remplir avant son téléchargement.

Voici un exemple de fichier CSV rempli:

name.firstName, name.lastName, biographie, twitter, facebook, linkedin Jamie, Munro, Jamie est développeur web et auteur ", Mike, Wilson, Mike est développeur web et auteur Node.js,,,

Cet exemple, une fois téléchargé, créera deux auteurs: moi-même et un ami qui a écrit un livre sur Node.js il y a quelques années. Vous remarquerez peut-être qu’à la fin de chaque ligne figurent trois virgules ",,". Ceci est fait pour abréger l'exemple. Je n'ai pas renseigné les propriétés du réseau social (gazouillement, Facebook, et linkedin).

Les pièces du puzzle commencent à se rassembler et à former une image. Passons à la viande et aux pommes de terre de cet exemple et analysons ce fichier CSV. le index.js Le fichier nécessite une mise à jour pour se connecter à MongoDB et créer un nouvel itinéraire POST qui acceptera le téléchargement du fichier:

var app = require ('express') (); var fileUpload = require ('express-fileupload'); var mangouste = require ('mangouste'); var server = require ('http'). Server (app); app.use (fileUpload ()); server.listen (80); mongoose.connect ('mongodb: // localhost / csvimport'); app.get ('/', fonction (req, res) res.sendFile (__ dirname + '/index.html');); var template = require ('./ template.js'); app.get ('/ template', template.get); var upload = require ('./ upload.js'); app.post ('/', upload.post);

Avec une connexion à la base de données et un nouvel itinéraire POST configurés, il est temps d'analyser le fichier CSV. Heureusement, il existe plusieurs grandes bibliothèques qui facilitent ce travail. J'ai choisi d'utiliser le fast-csv package pouvant être installé avec la commande suivante:

npm installer fast-csv --save

La route POST a été créée de la même manière que la route modèle, qui appelle une poster fonction de la upload.js fichier. Il n'est pas nécessaire de placer ces fonctions dans des fichiers séparés; Cependant, j'aime créer des fichiers séparés pour ces routes, car cela aide à garder le code agréable et organisé..

Soumission de données

Et enfin, créons le upload.js fichier qui contient le poster fonction appelée lorsque le formulaire créé précédemment est soumis:

var csv = require ('fast-csv'); var mangouste = require ('mangouste'); var Author = require ('./ author'); exports.post = function (req, res) if (! req.files) renvoie res.status (400) .send ('Aucun fichier n'a été téléchargé.'); var authorFile = req.files.file; var auteurs = []; csv .fromString (authorFile.data.toString (), en-têtes: true, ignoreEmpty: true) .on ("données", fonction (données) données ['_ id'] = new mongoose.Types.ObjectId (); authors.push (data);) .on ("end", function () Author.create (auteurs, function (err, documents) if (err) renvoie err;); res.send (authors.length + 'Les auteurs ont été téléchargés avec succès.');); ;

Un peu se passe dans ce fichier. Les trois premières lignes incluent les packages nécessaires pour analyser et sauvegarder les données CSV..

Ensuite, le poster la fonction est définie et exportée pour être utilisée par le index.js fichier. À l'intérieur de cette fonction est l'endroit où la magie a lieu.

La fonction vérifie d’abord qu’un fichier est contenu dans le corps de la demande. Si ce n'est pas le cas, une erreur est renvoyée, indiquant qu'un fichier doit être téléchargé..

Lorsqu'un fichier a été téléchargé, une référence au fichier est enregistrée dans une variable appelée authorFile. Ceci est fait en accédant à la des dossiers tableau et le fichier propriété dans le tableau. le fichier propriété correspond au nom de mon nom d'entrée de fichier que j'ai défini pour la première fois dans le index.html Exemple.

J'ai aussi créé un auteurs tableau qui sera rempli lorsque le fichier CSV sera analysé. Ce tableau sera utilisé pour sauvegarder les données dans la base de données.

le fast-csv bibliothèque est maintenant appelée en tirant parti de la fromString une fonction. Cette fonction accepte le fichier CSV en tant que chaîne. J'ai extrait la ficelle du authorFile.data propriété. le Les données propriété contient le contenu de mon fichier CSV téléchargé.

J'ai inclus deux options au fast-csv une fonction: en-têtes et ignorer le vide. Ce sont tous deux mis à vrai. Cela indique à la bibliothèque que la première ligne du fichier CSV contient les en-têtes et que les lignes vides doivent être ignorées..

Avec les options configurées, j’ai configuré deux fonctions d’écoute appelées lorsque le Les données événement et le fin événement sont déclenchés. le Les données event est appelé une fois pour chaque ligne du fichier CSV. Cet événement contient un objet JavaScript des données analysées..

Je mets à jour cet objet pour inclure le _id propriété de l'auteur Schema avec un nouveau ObjectId. Cet objet est ensuite ajouté à la auteurs tableau.

Lorsque le fichier CSV a été entièrement analysé, le fin l'événement est déclenché. Dans la fonction de rappel d'événement, j'appelle le créer fonction sur le modèle Author, en passant le tableau de auteurs à cela.

Si une erreur survient lors de la tentative d’enregistrement du tableau, une exception est levée. sinon, un message de réussite s'affiche pour l'utilisateur, indiquant le nombre d'auteurs téléchargés et enregistrés dans la base de données..

Si vous souhaitez voir le code source complet, j'ai créé un référentiel GitHub avec le code.

Conclusion

Dans mon exemple, je n'ai téléchargé que quelques enregistrements. Si votre cas d'utilisation nécessite la possibilité de télécharger des milliers d'enregistrements, il peut être judicieux de les enregistrer en plusieurs morceaux..

Cela peut être fait de plusieurs manières. Si je devais le mettre en œuvre, je suggérerais de mettre à jour le Les données fonction de rappel pour vérifier la longueur du tableau authors. Lorsque le tableau dépasse votre longueur définie, par exemple, 100, appelez le Auteur.créer fonction sur le tableau, puis réinitialiser le tableau à vide. Cela permettra ensuite de sauvegarder les enregistrements par tranches de 100. Assurez-vous de laisser le dernier créer appeler le fin fonction de rappel pour sauvegarder les enregistrements finaux.

Prendre plaisir!