introduction
Lorsque vous travaillez avecNode.js, vous pouvez vous retrouver en train de développer un projet qui stocke et interroge des données. Dans ce cas, vous devrez choisir une solution de base de données adaptée aux types de données et de requêtes de votre application.
Dans ce didacticiel, vous allez intégrer une base de donnéesMongoDB à une application Node existante. LesNoSQL databases comme MongoDB peuvent être utiles si vos besoins en données incluent l'évolutivité et la flexibilité. MongoDB s'intègre également bien avec Node car il est conçu pour fonctionner de manière asynchrone avec les objetsJSON.
Pour intégrer MongoDB dans votre projet, vous utiliserez lesObject Document Mapper (ODM)Mongoose pour créer des schémas et des modèles pour vos données d'application. Cela vous permettra d'organiser le code de votre application en suivant le modèle architectural demodel-view-controller (MVC), ce qui vous permet de séparer la logique de la façon dont votre application gère les entrées utilisateur de la façon dont vos données sont structurées et rendues à l'utilisateur. L'utilisation de ce modèle peut faciliter les tests et le développement futurs en introduisant une séparation des problèmes dans votre base de code.
À la fin du didacticiel, vous aurez une application d’information sur les requins qui utilisera les informations fournies par les utilisateurs sur leurs requins préférés et les affichera dans le navigateur:
Conditions préalables
-
Une machine ou un serveur de développement local exécutant Ubuntu 18.04, avec un utilisateur non root avec les privilèges
sudo
et un pare-feu actif. Pour obtenir des conseils sur la façon de les configurer sur un serveur 18.04, veuillez consulter ceInitial Server Setup guide. -
Node.js and npm installed on your machine or server, following these instructions on installing with the PPA managed by NodeSource.
-
MongoDB installé sur votre machine ou serveur, après l'étape 1 deHow To Install MongoDB in Ubuntu 18.04.
[[step-1 -—- creating-a-mongo-user]] == Étape 1 - Création d'un utilisateur Mongo
Avant de commencer à utiliser le code de l’application, nous allons créer un utilisateur administratif qui aura accès à la base de données de notre application. Cet utilisateur aura des privilèges administratifs sur toutes les bases de données, ce qui vous donnera la possibilité de changer de base de données et de créer de nouvelles bases de données selon vos besoins.
Tout d’abord, vérifiez que MongoDB est en cours d’exécution sur votre serveur:
sudo systemctl status mongodb
La sortie suivante indique que MongoDB est en cours d'exécution:
Output● mongodb.service - An object/document-oriented database
Loaded: loaded (/lib/systemd/system/mongodb.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2019-01-31 21:07:25 UTC; 21min ago
...
Ensuite, ouvrez le shell Mongo pour créer votre utilisateur:
mongo
Cela vous déposera dans un shell administratif:
OutputMongoDB shell version v3.6.3
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.3
...
>
Vous verrez des avertissements administratifs lorsque vous ouvrirez le shell en raison de votre accès illimité à la base de donnéesadmin
. Vous pouvez en savoir plus sur la restriction de cet accès en lisantHow To Install and Secure MongoDB on Ubuntu 16.04, lorsque vous passez à une configuration de production.
Pour l'instant, vous pouvez utiliser votre accès à la base de donnéesadmin
pour créer un utilisateur avec les privilègesuserAdminAnyDatabase
, ce qui permettra un accès protégé par mot de passe aux bases de données de votre application.
Dans le shell, indiquez que vous souhaitez utiliser la base de donnéesadmin
pour créer votre utilisateur:
use admin
Ensuite, créez un rôle et un mot de passe en ajoutant un nom d'utilisateur et un mot de passe avec la commandedb.createUser
. Après avoir tapé cette commande, le shell ajoutera trois points avant chaque ligne jusqu'à ce que la commande soit terminée. Assurez-vous de remplacer l'utilisateur et le mot de passe fournis ici par vos propres nom d'utilisateur et mot de passe:
db.createUser(
{
user: "sammy",
pwd: "your_password",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
}
)
Cela crée une entrée pour l'utilisateursammy
dans la base de donnéesadmin
. Le nom d'utilisateur que vous sélectionnez et la base de donnéesadmin
serviront d'identificateurs pour votre utilisateur.
La sortie de l'ensemble du processus ressemblera à ceci, y compris le message indiquant que l'entrée a réussi:
Output> db.createUser(
... {
... user: "sammy",
... pwd: "your_password",
... roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
... }
...)
Successfully added user: {
"user" : "sammy",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
}
Avec votre utilisateur et votre mot de passe créés, vous pouvez maintenant quitter le shell Mongo:
exit
Maintenant que vous avez créé votre utilisateur de base de données, vous pouvez cloner le code du projet de démarrage et ajouter la bibliothèque Mongoose, ce qui vous permettra d'implémenter des schémas et des modèles pour les collections de vos bases de données.
[[step-2 -—- ajoutant-mongoose-and-database-information-to-the-project]] == Étape 2 - Ajout d'informations sur la mangouste et la base de données au projet
Notre prochaine étape consistera à cloner le code de démarrage de l'application et à ajouter Mongoose et les informations de notre base de données MongoDB au projet.
Dans le répertoire personnel de votre utilisateur non root, clonez lesnodejs-image-demo
repository à partir desDigitalOcean Community GitHub account. Ce référentiel comprend le code de la configuration décrite dansHow To Build a Node.js Application with Docker.
Clonez le référentiel dans un répertoire appelénode_project
:
git clone https://github.com/do-community/nodejs-image-demo.git node_project
Accédez au répertoirenode_project
:
cd node_project
Avant de modifier le code du projet, examinons la structure du projet à l’aide de la commandetree
.
[.Remarque]##
Tip:tree
est une commande utile pour visualiser les structures de fichiers et de répertoires à partir de la ligne de commande. Vous pouvez l'installer avec la commande suivante:
sudo apt install tree
Pour l'utiliser,cd
dans un répertoire donné et tapeztree
. Vous pouvez également fournir le chemin d'accès au point de départ avec une commande comme:
tree /home/sammy/sammys-project
Tapez ce qui suit pour consulter le répertoirenode_project
:
tree
La structure du projet actuel ressemble à ceci:
Output├── Dockerfile
├── README.md
├── app.js
├── package-lock.json
├── package.json
└── views
├── css
│ └── styles.css
├── index.html
└── sharks.html
Nous ajouterons des répertoires à ce projet au fur et à mesure que nous avancerons dans le didacticiel, ettree
sera une commande utile pour nous aider à suivre notre progression.
Ensuite, ajoutez le package npmmongoose
au projet avec la commandenpm install
:
npm install mongoose
Cette commande créera un répertoirenode_modules
dans le répertoire de votre projet, en utilisant les dépendances répertoriées dans le fichierpackage.json
du projet, et ajouteramongoose
à ce répertoire. Il ajoutera égalementmongoose
aux dépendances répertoriées dans votre fichierpackage.json
. Pour une discussion plus détaillée depackage.json
, veuillez consulterStep 1 dansHow To Build a Node.js Application with Docker.
Avant de créer des schémas ou des modèles Mongoose, nous allons ajouter les informations de connexion de notre base de données afin que notre application puisse se connecter à notre base de données.
Afin de dissocier au maximum les préoccupations de votre application, créez un fichier séparé pour les informations de connexion à votre base de données appelédb.js
. Vous pouvez ouvrir ce fichier avecnano
ou votre éditeur préféré:
nano db.js
Tout d'abord, importez lesmongoose
module à l'aide de la fonctionrequire
:
~/node_project/db.js
const mongoose = require('mongoose');
Cela vous donnera accès aux méthodes intégrées de Mongoose, que vous utiliserez pour créer la connexion à votre base de données.
Ensuite, ajoutez lesconstantsuivants pour définir les informations pour l'URI de connexion de Mongo. Bien que le nom d'utilisateur et le mot de passe soient facultatifs, nous les inclurons afin de pouvoir exiger une authentification pour notre base de données. Assurez-vous de remplacer le nom d'utilisateur et le mot de passe ci-dessous par vos propres informations, et n'hésitez pas à appeler la base de données autre que'sharkinfo'
si vous préférez:
~/node_project/db.js
const mongoose = require('mongoose');
const MONGO_USERNAME = 'sammy';
const MONGO_PASSWORD = 'your_password';
const MONGO_HOSTNAME = '127.0.0.1';
const MONGO_PORT = '27017';
const MONGO_DB = 'sharkinfo';
Comme nous exécutons notre base de données localement, nous avons utilisé127.0.0.1
comme nom d'hôte. Cela changerait dans d'autres contextes de développement: par exemple, si vous utilisez un serveur de base de données distinct ou travaillez avec plusieurs noeuds dans un flux de travail conteneurisé.
Enfin, définissez une constante pour l'URI et créez la connexion à l'aide de la méthodemongoose.connect()
:
~/node_project/db.js
...
const url = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?authSource=admin`;
mongoose.connect(url, {useNewUrlParser: true});
Notez que dans l'URI, nous avons spécifié lesauthSource
de notre utilisateur comme base de donnéesadmin
. Cela est nécessaire car nous avons spécifié un nom d'utilisateur dans notre chaîne de connexion. L'utilisation de l'indicateuruseNewUrlParser
avecmongoose.connect()
spécifie que nous voulons utiliser lesnew URL parser de Mongo.
Enregistrez et fermez le fichier une fois l’édition terminée.
Enfin, ajoutez les informations de connexion à la base de données dans le fichierapp.js
afin que l'application puisse les utiliser. Ouvrirapp.js
:
nano app.js
Les premières lignes du fichier ressembleront à ceci:
~/node_project/app.js
const express = require('express');
const app = express();
const router = express.Router();
const path = __dirname + '/views/';
...
Sous la définition de la constanterouter
, située près du haut du fichier, ajoutez la ligne suivante:
~/node_project/app.js
...
const router = express.Router();
const db = require('./db');
const path = __dirname + '/views/';
...
Cela indique à l'application d'utiliser les informations de connexion à la base de données spécifiées dansdb.js
.
Enregistrez et fermez le fichier une fois l’édition terminée.
Avec les informations de votre base de données en place et Mongoose ajouté à votre projet, vous êtes prêt à créer les schémas et les modèles qui façonneront les données de votre collectionsharks
.
[[step-3 -—- creation-mongoose-schemas-and-models]] == Étape 3 - Création de schémas et de modèles Mongoose
Notre prochaine étape sera de réfléchir à la structure de la collectionsharks
que les utilisateurs créeront dans la base de donnéessharkinfo
avec leur entrée. Quelle structure voulons-nous que ces documents créés aient? La page d'informations sur les requins de notre application actuelle inclut des informations sur les différents requins et leurs comportements:
Conformément à ce thème, les utilisateurs peuvent ajouter de nouveaux requins avec des détails sur leur caractère général. Cet objectif déterminera la manière dont nous créons notre schéma.
Pour garder vos schémas et modèles distincts des autres parties de votre application, créez un répertoiremodels
dans le répertoire actuel du projet:
mkdir models
Ensuite, ouvrez un fichier appelésharks.js
pour créer votre schéma et votre modèle:
nano models/sharks.js
Importez le modulemongoose
en haut du fichier:
~/node_project/models/sharks.js
const mongoose = require('mongoose');
En dessous, définissez un objetSchema
à utiliser comme base de votre schéma de requin:
~/node_project/models/sharks.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
Vous pouvez maintenant définir les champs que vous souhaitez inclure dans votre schéma. Parce que nous voulons créer une collection avec des requins individuels et des informations sur leurs comportements, incluons unname
key et une clécharacter
. Ajoutez le schémaShark
suivant sous vos définitions de constante:
~/node_project/models/sharks.js
...
const Shark = new Schema ({
name: { type: String, required: true },
character: { type: String, required: true },
});
Cette définition comprend des informations sur le type d'entrée que nous attendons des utilisateurs - dans ce cas, unstring - et si cette entrée est requise ou non.
Enfin, créez le modèleShark
à l’aide desmodel()
function de Mongoose. Ce modèle vous permettra d'interroger les documents de votre collection et de valider de nouveaux documents. Ajoutez la ligne suivante au bas du fichier:
~/node_project/models/sharks.js
...
module.exports = mongoose.model('Shark', Shark)
Cette dernière ligne rend notre modèleShark
disponible en tant que module utilisant lesmodule.exports
property. Cette propriété définit les valeurs que le module exportera, les rendant disponibles pour une utilisation ultérieure dans l'application.
Le fichiermodels/sharks.js
terminé ressemble à ceci:
~/node_project/models/sharks.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Shark = new Schema ({
name: { type: String, required: true },
character: { type: String, required: true },
});
module.exports = mongoose.model('Shark', Shark)
Enregistrez et fermez le fichier une fois l’édition terminée.
Une fois le schéma et le modèle deShark
en place, vous pouvez commencer à travailler sur la logique qui déterminera comment votre application gérera les entrées utilisateur.
[[step-4 -—- creation-controllers]] == Étape 4 - Création de contrôleurs
Notre prochaine étape consistera à créer le composant contrôleur qui déterminera comment l’entrée de l’utilisateur est sauvegardée dans notre base de données et renvoyée à l’utilisateur.
Commencez par créer un répertoire pour le contrôleur:
mkdir controllers
Ensuite, ouvrez un fichier dans ce dossier appelésharks.js
:
nano controllers/sharks.js
En haut du fichier, nous allons importer le module avec notre modèleShark
afin de pouvoir l’utiliser dans la logique de notre contrôleur. Nous importerons également lespath
module pour accéder aux utilitaires qui nous permettront de définir le chemin vers le formulaire où les utilisateurs entreront leurs requins.
Ajoutez les fonctionsrequire
suivantes au début du fichier:
~/node_project/controllers/sharks.js
const path = require('path');
const Shark = require('../models/sharks');
Ensuite, nous allons écrire une séquence de fonctions que nous allons exporter avec le module contrôleur en utilisant lesexports
shortcut de Node. Ces fonctions comprendront les trois tâches liées aux données de requin de nos utilisateurs:
-
Envoi aux utilisateurs du formulaire de saisie de requin.
-
Créer une nouvelle entrée de requin.
-
Afficher les requins aux utilisateurs.
Pour commencer, créez une fonctionindex
pour afficher la page des requins avec le formulaire de saisie. Ajoutez cette fonction sous vos importations:
~/node_project/controllers/sharks.js
...
exports.index = function (req, res) {
res.sendFile(path.resolve('views/sharks.html'));
};
Ensuite, sous la fonctionindex
, ajoutez une fonction appeléecreate
pour créer une nouvelle entrée de requin dans votre collectionsharks
:
~/node_project/controllers/sharks.js
...
exports.create = function (req, res) {
var newShark = new Shark(req.body);
console.log(req.body);
newShark.save(function (err) {
if(err) {
res.status(400).send('Unable to save shark to database');
} else {
res.redirect('/sharks/getshark');
}
});
};
Cette fonction sera appelée lorsqu'un utilisateur publie des données de requin dans le formulaire de la pagesharks.html
. Nous créerons la route avec ce point de terminaison POST plus tard dans le didacticiel lorsque nous créerons les routes de notre application. Avec lesbody
de la requête POST, notre fonctioncreate
créera un nouvel objet document requin, ici appelénewShark
, en utilisant le modèleShark
que nous avons importé. Nous avons ajouté unconsole.log
method pour afficher l'entrée shark dans la console afin de vérifier que notre méthode POST fonctionne comme prévu, mais vous devriez vous sentir libre de l'omettre si vous préférez.
En utilisant l’objetnewShark
, la fonctioncreate
appellera alors lesmodel.save()
method de Mongoose pour créer un nouveau document requin en utilisant les clés que vous avez définies dans le modèleShark
. Cecallback function suit lesstandard Node callback pattern:callback(error, results)
. En cas d'erreur, nous enverrons un message signalant l'erreur à nos utilisateurs, et en cas de succès, nous utiliserons lesres.redirect()
method pour renvoyer les utilisateurs vers le point final qui leur rendra leurs informations de requin. dans le navigateur.
Enfin, la fonctionlist
affichera le contenu de la collection à l’utilisateur. Ajoutez le code suivant sous la fonctioncreate
:
~/node_project/controllers/sharks.js
...
exports.list = function (req, res) {
Shark.find({}).exec(function (err, sharks) {
if (err) {
return res.send(500, err);
}
res.render('getshark', {
sharks: sharks
});
});
};
Cette fonction utilise le modèleShark
avec lesmodel.find()
method de Mongoose pour renvoyer les requins qui ont été saisis dans la collectionsharks
. Il le fait en renvoyant l'objet de requête - dans ce cas, toutes les entrées de la collectionsharks
- comme une promesse, en utilisant lesexec()
function de Mongoose. En cas d'erreur, la fonction de rappel enverra une erreur 500.
L'objet de requête retourné avec la collectionsharks
sera rendu dans une pagegetshark
que nous créerons à l'étape suivante en utilisant le langage de création de modèlesEJS.
Le fichier fini ressemblera à ceci:
~/node_project/controllers/sharks.js
const path = require('path');
const Shark = require('../models/sharks');
exports.index = function (req, res) {
res.sendFile(path.resolve('views/sharks.html'));
};
exports.create = function (req, res) {
var newShark = new Shark(req.body);
console.log(req.body);
newShark.save(function (err) {
if(err) {
res.status(400).send('Unable to save shark to database');
} else {
res.redirect('/sharks/getshark');
}
});
};
exports.list = function (req, res) {
Shark.find({}).exec(function (err, sharks) {
if (err) {
return res.send(500, err);
}
res.render('getshark', {
sharks: sharks
});
});
};
Gardez à l'esprit que bien que nous n'utilisions pasarrow functions ici, vous souhaiterez peut-être les inclure lorsque vous itérez sur ce code dans votre propre processus de développement.
Enregistrez et fermez le fichier une fois l’édition terminée.
Avant de passer à l'étape suivante, vous pouvez réexécutertree
à partir de votre répertoirenode_project
pour afficher la structure du projet à ce stade. Cette fois, par souci de brièveté, nous dirons àtree
d'omettre le répertoirenode_modules
en utilisant l'option-I
:
tree -I node_modules
Avec les ajouts que vous avez faits, la structure de votre projet ressemblera à ceci:
Output├── Dockerfile
├── README.md
├── app.js
├── controllers
│ └── sharks.js
├── db.js
├── models
│ └── sharks.js
├── package-lock.json
├── package.json
└── views
├── css
│ └── styles.css
├── index.html
└── sharks.html
Maintenant que vous avez un composant de contrôleur pour diriger la manière dont les entrées de l'utilisateur sont enregistrées et renvoyées à l'utilisateur, vous pouvez passer à la création des vues qui implémenteront la logique de votre contrôleur.
[[step-5 -—- using-ejs-and-express-middleware-to-collect-and-render-data]] == Étape 5 - Utilisation d'EJS et d'Express Middleware pour collecter et restituer des données
Pour permettre à notre application de fonctionner avec les données des utilisateurs, nous allons faire deux choses: tout d'abord, nous allons inclure une fonction middleware Express intégrée,urlencoded()
, qui permettra à notre application d'analyser les données saisies par nos utilisateurs. Deuxièmement, nous allons ajouter des balises de modèle à nos vues pour permettre une interaction dynamique avec les données utilisateur dans notre code.
Pour utiliser la fonctionurlencoded()
d'Express, ouvrez d'abord votre fichierapp.js
:
nano app.js
Au-dessus de votre fonctionexpress.static()
, ajoutez la ligne suivante:
~/node_project/app.js
...
app.use(express.urlencoded({ extended: true }));
app.use(express.static(path));
...
L'ajout de cette fonction permettra d'accéder aux données POST analysées à partir de notre formulaire d'informations sur les requins. Nous spécifionstrue
avec l'optionextended
pour permettre une plus grande flexibilité dans le type de données que notre application analysera (y compris des choses comme les objets imbriqués). Veuillez consulter lesfunction documentation pour plus d'informations sur les options.
Enregistrez et fermez le fichier une fois l’édition terminée.
Ensuite, nous allons ajouter une fonctionnalité de modèle à nos vues. Tout d'abord, installez lesejs
package avecnpm install
:
npm install ejs
Ensuite, ouvrez le fichiersharks.html
dans le dossierviews
:
nano views/sharks.html
À l'étape 3, nous avons examiné cette page pour déterminer comment nous devrions écrire notre schéma et notre modèle Mongoose:
Maintenant, plutôt que d'avoir deux colonneslayout, nous allons introduire une troisième colonne avec un formulaire où les utilisateurs peuvent entrer des informations sur les requins.
Dans un premier temps, modifiez les dimensions des colonnes existantes en4
pour créer trois colonnes de taille égale. Notez que vous devrez effectuer cette modification sur les deux lignes qui lisent actuellement<div class="col-lg-6">
. Ceux-ci deviendront tous deux des<div class="col-lg-4">
:
~/node_project/views/sharks.html
...
Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.
Other sharks are known to be friendly and welcoming!
Pour une introduction au système de grille de Bootstrap, y compris ses dispositions de lignes et de colonnes, veuillez consulter ceintroduction to Bootstrap.
Ajoutez ensuite une autre colonne incluant le noeud final nommé pour la demande POST avec les données de requin de l'utilisateur et les balises de modèle EJS qui captureront ces données. Cette colonne ira sous les balises de fermeture</p>
et</div>
de la colonne précédente et au-dessus des balises de fermeture pour la ligne, le conteneur et le document HTML. Ces balises de fermeture sont déjà en place dans votre code; ils sont également marqués ci-dessous avec des commentaires. Laissez-les en place lorsque vous ajoutez le code suivant pour créer la nouvelle colonne:
~/node_project/views/sharks.html
...