10. NoSQL

10.1. Definición y ejemplos

  • Las bases NoSQL permiten el guardado y recuperación de datos como las bases SQL pero sin el sistema de tablas, usando, por ejemplo, sistemas de clave-valor. Sirven en situaciones en que las bases de datos tradicionales (relacionales) no cumplen con las expectativas (gran cantidad de datos, equipos con pocos recursos,…)
  • Algunos ejemplos son: MongoDB, Cassandra y Redis

10.2. MongoDB

10.2.1 Instalación en Ubuntu Server

10.2.2. Uso de MongoDB

  • Los elementos básicos en MongoDB son tres:
    • La base de datos (“database”)
    • La colección (“collection”, como una tabla en SQL)
    • El documento (“document”, como una fila en SQL)
  • Para iniciar el servidor (usa el puerto 27017)
    sudo service mongod start (primera vez)
  • Si se crea una carpeta /data/db con los permisos del usuario deseado, puede iniciarse el servidor con mongod --port 27017. Si se usa otra carpeta (dentro de /data) hay que añadir la opción --dbpath y la ruta completa. Además, para que se ejecute en segundo plano (sin ocupar una ventana), puede usarse la expresión & y cerrar sesión.
  • Inciar el cliente
    mongo (se conecta a 127.0.0.1:27017) mongo --host <<direccion:puerto>> mongo --port 27017
  • Programa cliente para Windows
    • Robo 3T
    • MongoDB Compass Community
  • Para acceder desde otro dominio
    • mongod --auth --dbpath /data/db --bind_ip_all
  • Abrir puerto tcp en router (27017 por defecto)
  • Accerder a la lista de comandos
    • db.help()
  • Acceder a estadísticas
    • db.stats()
  • Añadir usuario administrador y activar el control de acceso
    mongod --port 27017 --dbpath /data/db1 & mongo --port 27017 use admin db.createUser(   {     user: "myUserAdmin",     pwd: "abc123",     roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]   } )
    • cerrar mongo (quit())
    • cerrar mongod (ctrl+c)
    • mongod –-auth --port 27017 --dbpath /data/db1
    • mongo --port 27017 -u usuario -p --authenticationDatabase admin
  • NOTA: el administrador solo tiene permisos para crear otros usuarios, por lo que es necesario crear un usuario para manejar la base de datos
    • use <<base>>
    • db.createUser(...) (similar a crear un administrador, el "role" cambiaría por "readWrite" para permisos de lectura y escritura y "db" por la base elegida)
  • Crear o acceder a una base de datos (siempre hay que usarlo antes de ejecutar cualquier operación)
    • use nombrebase
    • Conocer en qué base nos encontramos
    • db
  • Acceder a la lista de bases de datos con permisos(deben tener al menos un documento para aparecer en la lista)
    • show dbs
  • Eliminar una base de datos (recuerda seleccionar antes la base y tener permisos en esa base)
    • db.dropDatabase()
  • Crear una colección
    • db.createCollection(“nombre”, [opciones])
  • Eliminar una colección
    • db.nombrecoleccion.drop()
  • Mostrar la lista de colecciones de una base
    • show collections
  • Insertar un documento (puede hacerse sin crear una colección antes)
    db.nombrecoleccion.insert({ _id: ObjectId(7df78ad8902c),  title: 'MongoDB Overview',  description: 'MongoDB is no sql database',  by: 'tutorials point',  url: 'http://www.tutorialspoint.com',  tags: ['mongodb', 'database', 'NoSQL'],  comments: [          {             user:'user1',             message: 'My first comment',             dateCreated: new Date(2013,11,10,2,35),             like: 0          }       ],  likes: 100 })
  • El campo _id no es obligatorio, se puede asignar automáticamente
  • Insertar varios documentos a la vez
    db.nombrecoleccion.insert([    {       title: 'MongoDB Overview',       description: 'MongoDB is no sql database'    },    {       title: 'NoSQL Database',       description: ‘NoSQL database doesn't have tables’    } ])
  • Modificar un documento
    • db.mycol.update({'columnacriterio':'valor'},{$set:{'title':'New MongoDB Tutorial'}})
  • Mostrar documentos en una colección
    • db.nombrecoleccion.find()
    • db.nombrecoleccion.find().pretty()
    • db.nombrecoleccion.find({},{"title":1,_id:0})
      • Para seleccionar las columnas a mostrar (1 muestra, 0 oculta, la _idaparece siempre que no se oculte expresamente)
    • db.nombrecoleccion.find({“columna”:”valor”})
    • db.nombrecoleccion.find({“columna”:{$lt:50}})
      • $lt: menor que
      • $lte: menor o igual a
      • $gt: mayor que
      • $gte: mayor o igual a
      • $ne: distinto a
    • db.listamov.find({added_collection:{$regex:/2016-*/}},{title:1, added_collection:1, _id:0})
    • db.mycol.find({ $and: [{columna1: valor1}, {columna2:valor2}] })
    • db.mycol.find({ $or: [{columna1: valor1}, {columna2:valor2}] })
    • db.mycol.find({"likes": {$gt:10}, $or: [{"by": "tutorials point"}, {"title": "MongoDB Overview"}] })
    • db.nombrecoleccion.find().limit(número)
    • db.nombrecoleccion.find().skip(número)
    • db.nombrecoleccion.find().sort(columna:1)
      • 1: orden ascendiente
      • -1: orden descendiente
    • db.nombrecoleccion.count()
  • Eliminar un documento
    • db.nombrecoleccion.remove(criterio, opciones)
  • Crear un índice
    • db.nombrecoleccion.ensureIndex({"title":1})
  • Mostrar los índices
    • db.nombrecoleccion.getIndexes()
  • Eliminar un índice
    • db.nombrecoleccion.dropIndex({"name":1})
  • Usar agregados con suma (similar al SUM() … GROUP BY de SQL)
    db.listamov.aggregate([ {     $group:{_id:"$categgr", total:{$sum:"$categsuma"}} } ])
  • Uniones
    • db.orders.aggregate([{$lookup:{from: "inventory",localField: "item", foreignField: "sku", as: "inventory_docs"}}])
  • Importar CSV
    • mongoimport -d basedatos -c listamov --type csv --file ./export2.csv --headerline (si el servidor tiene control de acceso, añadir: -u usuario -p pass --authenticationDatabase base)
  • Importar JSON
    • mongoimport --db <<base>> --collection <<coleccion>> --type json --file seed.json --jsonArray

 

10.2.3. Uso de MongoDB con Node.js

  • npm install mongodb (en la carpeta del archivo js)
  • const mongoClient = require('mongodb').MongoClient;
    const f = require('util').format;
    const user = encodeURIComponent('ricardo');
    const pass = encodeURIComponent('xxxxx');
    const authMechanism = 'DEFAULT';
    const authDatabase = encodeURIComponent('db_1');
    var url = f('mongodb://%s:%s@127.0.0.1:27017/?authMechanism=%s&authSource=%s', user, pass, authMechanism, authDatabase);
    mongoClient.connect(url, {useNewUrlParser: true}, function(err, db){
            if (err) throw err;
            var db1 = db.db('db_1');
            console.log('Conectado');
            db1.collection('tabla').findOne({}, function(err, result){
                    if (err) throw err;
                    console.log(result);
                    db.close();
            });
    });
  • var myobj = { name: "Company Inc", address: "Highway 37" };
    var myobj = [
        { name: 'John', address: 'Highway 71'},
        { name: 'Peter', address: 'Lowstreet 4'}
    ];
    dbo.collection("customers").insertOne(myobj, function(err,  res) {
            if (err) throw err;
            console.log("documento insertado");
            db.close();
         });
    dbo.collection(“customers”).insertMany(myobj, function(err,     res) {
            if (err) throw err;
            console.log("documento insertado");
            db.close();
                        });
    dbo.collection(‘tabla’).findOne({}, function(err, result){
        if(err) throw err;
        console.log(result.title);
        db.close();
    });
    dbo.collection("customers").find({}).toArray(function(err, result) {
        if (err) throw err;
        console.log(result);
        db.close();
      });
  • Ejemplo completo con módulo HTTP:
    var http = require('http');
    const mongoClient = require('mongodb').MongoClient;
    const f = require('util').format;
    const user = encodeURIComponent('ricardo');
    const pass = encodeURIComponent('xxxxx');
    const authMechanism = 'DEFAULT';
    const authDatabase = encodeURIComponent('db_1');
    const url = f('mongodb://%s:%s@localhost:27017/?authMechanism=%s&authSource=%s', user, pass, authMechanism, authDatabase);
    http.createServer(function(req, res){
      mongoClient.connect(url, {useNewUrlParser: true}, function(err, db){
        if (err) throw err;
        var db1 = db.db('db_1');
        res.write('Conectado a la basen');
        db1.collection('tabla').findOne({}, function(err, result){
          if (err) throw err;
          res.write("Resultado: " + result.name);
          res.end();
          db.close();
        });
      });
    }).listen(8080);
  • Ejemplo con varias acciones (métodos anidados)
    var MongoClient = require('mongodb').MongoClient,
    assert = require('assert');
     // Connection URL
    var url = 'mongodb://127.0.0.1:27017/';
     // Use connect method to connect to the Server
    MongoClient.connect(url, {useNewUrlParser:true}, function(err, db) {
        assert.equal(null, err);
        var dbo = db.db('basedatos');
        console.log("Connected correctly to server");
        // Insert a single document
        dbo.collection('tabla').insertOne({name:"ricardo"}, function(err, r) {
            assert.equal(null, err);
            assert.equal(1, r.insertedCount);
      console.log("añadido " + r.insertedCount);
            // Insert multiple documents
        dbo.collection('tabla').insertMany([{name:"jose"}, {name:"alberto"}], function(err, r) {
                assert.equal(null, err);
                assert.equal(2, r.insertedCount);
       console.log("añadido " + r.insertedCount);
                db.close();
            });
        });
    });

10.2.4. Uso de MongoDB con PHP y Apache

  1. Instalar php7.2-dev
  2. Instalar php-pear
  3. Instalar unzip
  4. sudo pecl install mongodb
  5. En /etc/php/7.2/apache2/php.ini (fijarse cual es el php.ini que funciona con phpinfo()), añadir: extension=mongodb.so
  6. Instalar composer (ver apartado 11.4.)
  7. php composer.phar require mongodb/mongodb
  8. En el archivo .php, añadir:
    <?php
       require ‘vendor/autoload.php’;
    ?>
  9. $cliente = new MongoDBClient("mongodb://127.0.0.1:27017");
        $coleccion = $cliente->basedatos->coleccion;
    $resultado = $coleccion->find(['name' => 'ricardo']);
    foreach ($resultado as $entrada){
    echo "<p>". $entrada['name'] ."</p>";
        }

10.3. Redis

10.3.1. Instalación del servidor

  1. wget http://download.redis.io/releases/redis-4.0.8.tar.gz
  2. tar xzf redis-4.0.8.tar.gz
  3. cd redis-4.0.8
  4. make
  5. src/redis-server

10.3.2. Uso del cliente

  1. src/redis-cli