Trabajando con MongoDB en PHP

MongoDB es una base de datos NoSQL gratuita y de código abierto desarrollada por MongoDB Inc.
Algunas de las fortalezas clave de MongoDB pueden resumirse de la siguiente manera:

  • Es una base de datos basada en documentos.
  • Es multiplataforma
  • Se ejecuta en un solo servidor, así como en arquitecturas distribuidas
  • Se puede usar para aplicaciones de escritorio y web
  • Utiliza objetos JSON para almacenar datos.
  • Puede usar JavaScript map-reduce para el procesamiento de información en el lado del servidor
  • Procesa grandes volúmenes de datos.
  • Agrega cálculos
  • Admite campos, consultas de rango y búsquedas de expresiones regulares.
  • Es una replicacion nativa

Instalar MongoDB

Suponiendo que estamos utilizando la nueva instalación de Ubuntu 16.10 (Yakkety Yak), los siguientes pasos describen cómo podemos configurar MongoDB:

1-Instalaremos MongoDB usando el siguiente comando de consola:

sudo apt-get update
sudo apt-get install -y mongodb

2-Para verificar que MongoDB se haya instalado y ejecutado correctamente, podemos ejecutar el siguiente comando:

sudo systemctl status mongodb.service

Esto debería darnos el siguiente resultado:

Configurar datos de muestra

Ejecutar el comando mongo en el terminal de Ubuntu nos lleva a un shell interactivo mongo. De aquí en adelante, con unos simples comandos, podemos agregar los datos de muestra:

use foggyline
db.products.insert({name: "iPhone 7", price: 650, weight: "138g"});
db.products.insert({name: "Samsung Galaxy S7", price: 670, weight: "152g"
});
db.products.insert({name: "Motorola Moto Z Play", price: 449.99, weight:
"165g" });
db.products.insert({name: "Google Pixel", price: 649.99, weight: "168g" });
db.products.insert({name: "HTC 10", price: 799, weight: "161g" });
show dbs
show collections

Esto debería darnos una salida muy similar a la siguiente captura de pantalla:

Con el uso de foggyline y db.products.find(), ahora podemos enumerar todas las entradas agregadas a la colección de productos:

Consulta a través de la extensión del controlador MongoDB

Tenemos que asegurarnos de tener instalada la extensión de controlador CLI de PHP y MongoDB:

sudo apt-get -y install php-pear
sudo apt-get -y install php7.0-dev
sudo apt-get -y install libcurl4-openssl-dev pkg-config libssl-dev
libsslcommon2-dev
sudo pecl install mongodb

Tras la ejecución exitosa de estos comandos, podemos confirmar que la extensión del controlador mongodb está instalada, como se muestra en la siguiente captura de pantalla:

Además de la extensión del controlador, también necesitamos un paquete de composer mongodb/mongodb agregado a nuestro directorio de proyectos. Podemos hacerlo ejecutando el siguiente comando de consola:

sudo apt-get -y install composer
composer require mongodb/mongodb

Suponiendo que tenemos el archivo mongo.php dentro de nuestro directorio de proyecto, todo lo que se necesita es cargar la biblioteca MongoDB y comenzar a trabajar con la base de datos Mongo:

<?php
require_once __DIR__. '/vendor/autoload.php';
// Code…

Conectando

Usando la extensión del controlador mongodb y la biblioteca PHP mongodb/mongodb, podemos conectarnos a la base de datos Mongo desde PHP usando la clase MongoDBDriverManager, de la siguiente manera:

<?php
require_once __DIR__ . '/vendor/autoload.php';
$manager = new MongoDBDriverManager('mongodb://localhost:27017');

Esta expresión de una sola línea buscará MongoDB en localhost bajo el puerto 27017.

Manejo de errores

Manejar errores es bastante sencillo con el bloque try…catch, como MongoDBDriverExceptionException se produce cada vez que se produce un error:

<?php
require_once __DIR__ . '/vendor/autoload.php';
try {
$manager = new MongoDBDriverManager('mongodb://localhost:27017');
} catch (MongoDBDriverExceptionException $e) {
echo $e->getMessage(), PHP_EOL;
exit;
}

Seleccionando

Obtener datos con MongoDB se reduce a trabajar con tres clases diferentes, MongoDBDriverManager, MongoDBDriverQuery y MongoDBDriverReadPreference:

<?php
require_once __DIR__ . '/vendor/autoload.php';
try {
$manager = new MongoDBDriverManager('mongodb://localhost:27017');
/* Select only the matching documents / $filter = [ 'price' => [ '$gte' => 619.99, ], ]; $queryOptions = [ / Return only the following fields in the matching documents / 'projection' => [ 'name' => 1, 'price' => 1, ], / Return the documents in descending order of price */
'sort' => [
'price' => -1
]
];
$query = new MongoDBDriverQuery($filter, $queryOptions);
$readPreference = new
MongoDBDriverReadPreference(MongoDBDriverReadPreference::RP_PRIMARY);
$products = $manager->executeQuery('foggyline.products', $query,
$readPreference);
foreach ($products as $product) {
echo $product->name, ': ', $product->price, PHP_EOL;
}
} catch (MongoDBDriverExceptionException $e) {
echo $e->getMessage(), PHP_EOL;
exit;
}

Esto da el siguiente resultado:

La lista de operadores de consulta que podemos pasar a $filter es bastante extensa, pero los siguientes operadores de comparación pueden ser los más interesantes:

  • $eq: estos coinciden con todos los valores que son iguales a un valor especificado
  • $gt: estos coinciden con todos los valores que son mayores que un valor especificado
  • $gte: estos coinciden con todos los valores que son mayores o iguales que un valor especificado
  • $lt: estos coinciden con todos los valores que son menores que un valor especificado
  • $lte: estos coinciden con todos los valores que son menores o iguales a un valor especificado
  • $ne: estos coinciden con todos los valores que no son iguales a un valor especificado
  • $in: estos coinciden con todos los valores especificados en una matriz
  • $nin: estos coinciden con los valores none que se especifican en una matriz

Echa un vistazo a https://docs.mongodb.com/manual/reference/operator/query/ para obtener una lista completa de los operadores de consulta y proyección de MongoDB.

La lista de opciones de consulta que podemos pasar a $queryOptions es igualmente impresionante, pero las siguientes opciones pueden ser las esenciales:

  • collation: permiten especificar reglas específicas del idioma para la comparación de cadenas
  • limit: permiten especificar la cantidad máxima de documentos a devolver
  • maxTimeMS: establece el límite de tiempo de las operaciones de procesamiento en milisegundos
  • projection: permiten especificar qué campos incluir en la devolución documentos
  • sort: permiten especificar el orden de clasificación de los resultados

Echa un vistazo a http://php.net/manual/en/mongodb-driver-query.construct.php para obtener una lista completa de las opciones de consulta de MongoDBDriverQuery.

Insertar

Escribir nuevos datos con MongoDB se reduce a trabajar con tres clases diferentes, MongoDBDriverManager, MongoDBDriverBulkWrite y MongoDBDriverWriteConcern:

<?php
require_once __DIR__ . '/vendor/autoload.php';
try {
$manager = new MongoDBDriverManager('mongodb://localhost:27017');
$bulkWrite = new MongoDBDriverBulkWrite;
$bulkWrite->insert([
'name' => 'iPhone 7 Black White',
'price' => 650,
'weight' => '138g'
]);
$bulkWrite->insert([
'name' => 'Samsung Galaxy S7 White',
'price' => 670,
'weight' => '152g'
]);
$writeConcern = new MongoDBDriverWriteConcern(MongoDBDriverWriteConcern::MAJORITY, 1000);
$result = $manager->executeBulkWrite('foggyline.products', $bulkWrite,
$writeConcern);
if ($result->getInsertedCount()) {
echo 'Record(s) saved successfully.', PHP_EOL;
} else {
echo 'Error occurred.', PHP_EOL;
}
} catch (MongoDBDriverExceptionException $e) {
echo $e->getMessage(), PHP_EOL;
exit;
}

La instancia de BulkWrite puede almacenar una o más instrucciones de inserción a través del método insert(). Luego simplemente pasamos $bulkWrite y $writeConcern para executeBulkWrite() en la instancia de $manager. Una vez ejecutados, podemos observar los registros recién agregados a través del shell mongo:

Actualización

La actualización de datos existentes es un proceso casi idéntico al de escribir datos nuevos. La diferencia obvia es el uso del método update() en la instancia de MongoDBDriverBulkWrite:

<?php
require_once __DIR__ . '/vendor/autoload.php';
try {
$manager = new MongoDBDriverManager('mongodb://localhost:27017');
$bulkWrite = new MongoDBDriverBulkWrite;
$bulkWrite->update(
['name' => 'iPhone 7 Black White'],
['$set' => [
'name' => 'iPhone 7 Black Black',
'price' => 649.99
]],
['multi' => true, 'upsert' => false]
);
$bulkWrite->update(
['name' => 'Samsung Galaxy S7 White'],
['$set' => [
'name' => 'Samsung Galaxy S7 Black',
'price' => 669.99
]],
['multi' => true, 'upsert' => false]
);
$writeConcern = new
MongoDBDriverWriteConcern(MongoDBDriverWriteConcern::MAJORITY, 1000);
$result = $manager->executeBulkWrite('foggyline.products', $bulkWrite,
$writeConcern);
if ($result->getModifiedCount()) {
echo 'Record(s) saved updated.', PHP_EOL;
} else {
echo 'Error occurred.', PHP_EOL;
}
} catch (MongoDBDriverExceptionException $e) {
echo $e->getMessage(), PHP_EOL;
exit;
}

El método update() acepta tres parámetros diferentes: filtro, un nuevo objeto y opciones de actualización. La opción múltiple aprobada en las opciones de actualización indica si se actualizarán los criterios de coincidencia de todos los documentos. La opción upsert aprobada en las opciones de actualización controla la creación de un nuevo registro si no se encuentra el registro existente. El cambio resultante se puede observar a través de la shell de mongo:

Borrando

La eliminación se realiza de manera similar a escribir y actualizar, ya que utiliza una instancia del objeto MongoDBDriverBulkWrite. Esta vez, estamos utilizando el método delete() de instancia, que acepta opciones de filtro y eliminación:

<?php
require_once __DIR__ . ‘/vendor/autoload.php’;
try {
$manager = new MongoDBDriverManager(‘mongodb://localhost:27017’);
$bulkWrite = new MongoDBDriverBulkWrite;
$bulkWrite->delete(
// filter
[
‘name’ => [
‘$regex’ => ‘^iPhone’
]
],
// Opciones de eliminar
[‘limit’ => false]
);
$writeConcern = new
MongoDBDriverWriteConcern(MongoDBDriverWriteConcern::MAJORITY, 1000);
$result = $manager->executeBulkWrite(‘foggyline.products’, $bulkWrite,
$writeConcern);
if ($result->getDeletedCount()) {
echo ‘Record(s) deleted.’, PHP_EOL;
} else {
echo ‘Error occurred.’, PHP_EOL;
}
} catch (MongoDBDriverExceptionException $e) {
echo $e->getMessage(), PHP_EOL;
exit;
}

Usando el valor falso para la opción de límite, estamos efectivamente solicitando eliminar todos los documentos coincidentes. Usando el shell mongo, podemos observar los cambios que se muestran en la siguiente captura de pantalla:

Transacciones

MongoDB no tiene un ACID completo (atomicidad, consistencia, aislamiento, durabilidad) en un sentido que tiene MySQL. Solo admite transacciones ACID a nivel de documento. Las transacciones de varios documentos no son compatibles. La falta de cumplimiento de ACID ciertamente limita su uso con plataformas que dependen de esta característica. Esto no quiere decir que MongoDB no se pueda usar con tales plataformas. Consideremos una popular plataforma de comercio electrónico Magento. No hay nada que impida que Magento agregue MongoDB a la mezcla. Si bien las características de MySQL pueden garantizar el cumplimiento de ACID en relación con la funcionalidad, MongoDB se puede usar dentro de la conjunción para cubrir partes de la funcionalidad del catálogo. Este tipo de simbiosis puede aportar fácilmente lo mejor de ambas características de la base de datos a nuestra plataforma.

Comparte