Taula de continguts

Accedint a MongoDB

MongoDB és una base de dades no-SQL orientada a document.

Aquest article està orientat a la connexió a MongoDB a través de diferents llenguatges de programació.

Es recomana utilitzar una versió avançada de MongoDB. Si la versió de MongoDB és 2.x o menor, algunes eines com Robomongo o Studio 3T no ens funcionaran bé. A Ubuntu 18.04 hi ha MongoDB > 3.x, cap problema, doncs (però a Ubuntu 16.04 tenien versions 2.x i no eren viables).

Recursos:

Importa amb mongorestore la base de dades de prova movies-mongo-dump.rar. La utilitat d'importació habitual és mongoimport, però en aquest cas farem servir mongorestore ja que les dades estan en format binari).

, , , , , , , , , , , , , ,


MongoDB i PHP

Instal·lació

Primer cal instal·lar el //driver// tal i com s'explica a la documentació. (Adaptar aquestes ordres a la versió adequada si fos necessari: p.ex. php-dev podria ser php7.2-dev ).

Per Ubuntu LTS això funcionaria:

$ sudo apt install php-dev php-pear
$ sudo pecl install mongodb

Afegim la llibreria a la instal·lació afegint a l'arxiu php.ini:

extension=mongodb.so

Cal mirar la documentació de la llibreria.

Exemple MongoDB amb PHP

Suposant una col·lecció bàsica com aquesta:

{
  "_id" : ObjectId("5e1b40a2d7a590a8d1709ab7"),
  "marca" : "Renault",
  "model" : "Twizzy"
}
{
  "_id" : ObjectId("5e1b40add7a590a8d1709ab8"),
  "marca" : "Seat",
  "model" : "León"
}

Cal mirar bé la documentació de PHP perquè hi ha diversos drivers i s'utilitzen de forma diferent. El què hem instal·lat correspon a aquesta doc: https://www.php.net/manual/es/book.mongodb.php

Aquest ens ha funcionat amb el següent exemple:

	use MongoDB\Driver\Manager as MongoManager;
	use MongoDB\Driver\Query as MongoQuery;

	$mongo = new MongoManager();
	$filter = [];
	$options = [];
	$query = new MongoQuery( $filter, $options );
	$cotxes = $mongo->executeQuery( "prova.cotxes", $query );
	
	foreach( $cotxes as $cotxe ) {
		echo $cotxe->marca." ".$cotxe->model."<br>\n";
	}


MongoDB amb NodeJS

Importa amb mongorestore la base de dades de prova movies-mongo-dump.rar.

Per saber més de NodeJS mira't els apunts a nodejs_express.

Instal·lació

Per connectar-nos disposem del Driver asíncron (mongodb) per a JavaScript. Pots instal·lar-lo amb

$ npm install mongodb

Les classes principals que utilitzarem són Cursor i Collection

Els cursors ben explicats aquí.

Connection Pooling

Per gestionar les connexions a MongoDB dins d'una aplicació web (concorrent per natura) es recomana fer 1 sola connexió per la app, i reutilitzar l'element db en cada request. Això ens proveirà el que anomenem connection pooling. El driver és intel·ligent i sap gestionar les diverses connexions de la forma més òptima per paral·lelitzar els accessos del servidor web.

Per inicar el projecte node, crea dins d'una carpeta:

$ npm init
$ npm install express body-parser ejs mongodb

Afegeix el codi a index.js i arrenca el servidor:

$ node index.js

Codi d'exmeple NodeJS i MongoDB

Doc inicial sobre les collections i cursors de MongoDB.

Exmple de connexió per a una pàgina web:

// framework express
var express = require('express');
// bodyparser ens permet processar variables GET i POST
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
// per renderitzar les plantilles (render)
app.set('view engine','ejs');
 
var mongo = require('mongodb').MongoClient;
var mongoClient;
 
// connexió a mongo i start app
mongo.connect('mongodb://localhost:27017', function( err, _client ) {
    // si no ens podem connectar, sortim
    if( err ) throw err;
    mongoClient = _client;
    // si no hi ha cap error de connexió, engeguem el servidor
    app.listen(3000, function () {
        console.log('Example app listening on http://localhost:3000 !');
    });
});
 
 
// view: llistat elements
app.get('/', function (req, res) {
    var db = mongoClient.db("cotxes");
    var opcions = {};
    var query = {};
    db.collection('cotxes').find( query, opcions ).toArray(function( err, docs ) {
        if( err ) {
            res.render( 'error', {msg:"error a la query"} );
            return;
        }
        // renderitzem la plantilla q hem de crear a views/cotxes.ejs
        res.render( 'cotxes', {"cotxes":docs} );
    });
});

// view: llistat elements en format JSON (API)
app.get('/api/movies', function (req, res) {
    var db = mongoClient.db("video");
    var fields = { _id:true, title:true, year:true };
    var query = {};
    var opcions = { limit:4, fields:fields };
    db.collection('movieDetails').find( query, opcions ).toArray(function( err, docs ) {
        if( err ) {
            res.send( JSON.stringify( {status:"error",msg:"error a la query"}) );
            return;
        }
        // transformem l'array "docs" en un string i el retornem tal qual
        res.send( JSON.stringify(docs) );
    });
});

Visita la web amb el browser a (cal abans crear les plantilles ejs descrites més avall)

http://localhost:3000

Prova la API amb la comanda:

$ curl localhost:3000/api/movies

A aquest codi caldrà afegir les plantilles error.ejs i cotxes.ejs a la carpeta views que renderitzarà finalment la llista de cotxes que ens ha retornat a docs. https://mongodb.github.io/node-mongodb-native/3.5/tutorials/collections/ És important remarcar que

ObjectID

De vegades voldrem accedir a diferents elements de la llibreria de MongoDB per a NodeJS. Per exemple, per generar ObjectIDs fes un cop d'ull a aquest codi.


Connectant amb MongoDB Atlas

Obriu-vos un compte a MongoDB Atlas que us permetrà crear un cluster MongoDB gratuït al núvol. Importeu les col·leccions d'exemple per poder fer proves.

Si busqueu com connectar al vostre cluster, us mostrarà un string del tipus:

mongodb+srv://pepe:[email protected]/mydb

… que significa que em puc connectar a l'usuari «pepe» amb password «pepe123» i accedir a la BD «mydb».

Modifiqueu el codi de l'aplicació perquè us connecti a la vostra instància Atlas. Penseu que no podeu crear un codi que contingui usuaris i contrasenyes i pujar-ho al sistema de control de versions (GitHub), ja que l'exposaríeu a altres usuaris i us hackejarien la base de dades fàcilment. Així, una bona pràctica de control de versions és posar el usuari i password del nostre cluster a les variables d'entorn, i al codi capturar-ho amb process.env.MYVAR:

Abans d'engegar l'aplicació haureu de ajustar les variables d'entorn amb

$ export DBUSER=admin
$ export DBPASS=P@ssw0rd
$ node app.js

// connexió a mongo i start app
var mongo = require('mongodb').MongoClient;
var mongoClient;
// consts
const PORT = process.env.PORT || 5000
const user = encodeURIComponent( process.env.DBUSER );
const pass = encodeURIComponent( process.env.DBPASS );
var dbConStr = "mongodb+srv://"+user+":"+pass+"@cluster0-metgf.mongodb.net/grades";
mongo.connect( dbConStr, function( err, _client ) {
    // si no ens podem connectar, sortim
    if( err ) throw err;
    mongoClient = _client;
    // si no hi ha cap error de connexió, engeguem el servidor
    app.listen(PORT, function () {
        console.log('Example app listening on http://localhost:'+PORT+' !');
    });
});

Contrasenyes segures

Aquest codi anterior captura les variables DBUSER i DBPASS de l'entorn de la shell, la qual cosa va bé, però resulta una mica incòmode ajustar les variables cada cop que engeguem la màquina. Per estalviar-nos aquest pas, podem posar les variable a l'arxiu .env, però afegint .env al .gitignore per evitar que pugem aquest arxiu amb contasenyes al repositori de codi.

Utilitza el paquet dotenv de npm per carregar les variables d'entorn de l'arxiu .env. Tindrem un arxiu '.env' com ara:

DBUSER=user
DBPASS=P@ssw0rd

I podem carregar-lo tal i com diu la documentació, amb:

require('dotenv').config()


Exercici DB films

Importa amb mongorestore la base de dades de prova movies-mongo-dump.rar.

Crea una web amb la base de dades de films que implementi:

  1. Visualització de llistat de pel·lícules paginades en grups de 6 per pàgina (configurable per una variable global).
  2. Possibilitat d'avançar i retrocedir en les pàgines.
  3. Mostrar la imatge indicada en el camp «poster» de la col·lecció movieDetails.
  4. Que mostri la descripció de la pel·lícula (camp «plot»), a més del títol.
  5. Habilitar botoó «edita» que permeti editar el títol i la descripció de la pel·lícula.
  6. Implementar una cerca entre els títols de pel·lícula per filtrar.
  7. Ampliar que les cerques també mirin als actors, directors i escriptors (writers).
  8. Implementar un sistema de valoracions de la pel·lícula (del 0 al 10 ).
  9. Filtrar que només es pugui valorar un cop amb el ID del cookie de sessió (quan canvia de IDsession es pot tornar a votar).