In questa lezione vedremo come interagire con MongoDB utilizzando il linguaggio di programmazione PHP, uno dei più utilizzati nell'ambito della programmazione web lato server.
Esistono diverse soluzioni per interagire con MongoDB tramite PHP, e le due principali sono i driver mongo e mongodb. In questa lezione faremo riferimento a mongodb
.
Installazione
Per prima cosa, vediamo come installare mongodb. Supponendo di lavorare su un sistema Linux basato su Debian (per esempio Ubuntu), possiamo reperire questo modulo tramite il comando git, installandolo subito a seguire:
$ git clone https://github.com/mongodb/mongo-php-driver.git
$ cd mongo-php-driver
$ git submodule sync && git submodule update --init
$ phpize
$ ./configure
$ make
$ sudo make install
Terminata l'installazione, non resta che aggiungere l'estensione relativa al modulo nel file php.ini:
extension=mongodb.so
Connessione al Database
Vediamo subito un esempio di utilizzo del modulo mongodb appena installato. In particolare, vedremo come effettuare una connessione ad un database denominato testdb, visualizzando inoltre alcune informazioni ad esso relative.
<?php
try {
$mng = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$stats = new MongoDB\Driver\Command(["dbstats" => 1]);
$res = $mng->executeCommand("testdb", $stats);
$stats = current($res->toArray());
print_r($stats);
} catch (MongoDB\Driver\Exception\Exception $e) {
//Errore
}
?>
Come si può intuire, MongoDB\Driver\Manager
rappresenta la classe che si occupa di mantenere le connessioni a MongoDB. Noi l'abbiamo utilizzata passando come argomento del costruittore la stringa di connessione al DBMS. A questo, per connetterci direttamente al database che ci interessa, utilizziamo il metodo executeCommand("testdb", $stats)
, dove il primo argomento è il nome del DB mentre il secondo argomento è un'istanza della classe MongoDB\Driver\Command
, che rappresenta il comando da eseguire.
L'oggetto $res
è un'istanza della classe MongoDB\Driver\Cursor
, che viene restituita da executeCommnad()
tutte le volte che l'esecuzione di un comando va a buon fine. Utilizziamo la funzione current()
, unitamente al metodo toArray()
di MongoDB\Driver\Cursor
per ottenere i risultati restituiti e contenuti nel cursore.
La funzione print_r($stats)
, infine, non fa altro che mostrare i risultati dell'esecuzione del comando, producendo un risultato simile al seguente:
stdClass Object
(
[db] => testdb
[collections] => 5
[objects] => 14
[avgObjSize] => 65.88767335
[dataSize] => 745
[storageSize] => 199848
[numExtents] => 3
[indexes] => 1
[indexSize] => 8176
[fileSize] => 261345593
[nsSizeMB] => 16
[dataFileVersion] => stdClass Object
(
[major] => 4
[minor] => 5
)
[ok] => 1
)
Possiamo ovviamento modificare la sintassi precedente per eseguire i comandi che ci fanno più comodo. Ad esempio, per ottenere la lista dei database sarà sufficiente modificare l'inizializzazione della variabile $stats
in questo modo:
$stats = new MongoDB\Driver\Command(["listDatabases" => 1]);
Leggere i dati
Per eseguire una query al fine di leggere i dati da un database MongoDB, si utilizza la classe MongoDB\Driver\Query
. Vediamo subito un esempio pratico:
<?php
try {
$mng = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$query = new MongoDB\Driver\Query([]);
$rows = $mng->executeQuery("testdb.cars", $query);
foreach ($rows as $row) {
echo "$row->name : $row->price\n";
}
} catch (MongoDB\Driver\Exception\Exception $e) {
//Errore
}
?>
L'esempio definisce una query (MongoDB\Driver\Query([])
), applicata poi alla collection testdb.cars mediante il metodo executeQuery()
. Poichè la query è definita passando come argomento un array vuoto, il risultato consisterà nella lettura di tutte le entry della collection specificata.
Tramite il ciclo foreach
finale, vengono quindi stampati tutti i risultati della query.
Filtraggio
Se vogliamo specificare un certo tipo di filtraggio dei dati, possiamo definire un array da utilizzare come argomento al metodo executeQuery()
. Per esempio, potremmo ottenere le entry della stessa collection utilizzata sopra, ma limitandoci a quelle con il campo name impostato a Fiat, sostituendo la riga di inizializzazione dell'oggetto $query
con la seguente:
$query = new MongoDB\Driver\Query([ 'name' => 'Fiat' ]);
Proiezioni
L'operazione di proiezione ci permette di specificare quali campi siamo interessati ad ottenere come risultato di una query. Modifichiamo ancora l'oggetto $query
dell'esempio precedente, aggiungendo un ulteriore parametro al costruttore:
$filter = [ 'name' => 'Fiat' ];
$options = [ 'projection' => ['_id' => 0] ];
$query = new MongoDB\Driver\Query($filter, $options);
In questo caso, per comodità, abbiamo definito un array $filter
che specifica il filtraggio da applicare ai risultati della query, ed un ulteriore array $options
che, in questo caso, servirà a nascondere il campo _id
dai risultati della query. Tali array sono passati quindi al costruttore dell'oggetto $query
.
Ordinare e limitare il numero di risultati
Utilizzando il modulo mongodb di PHP, è anche possibile limitare il numero di risultati ottenuti come output di una query. Inoltre, possiamo anche stabilire un criterio di ordinamento da applicare ad essi. Entrambe queste possibilità sono implementate come opzioni aggiuntive, che possiamo quindi passare come secondo argomento del costruttore della classe MongoDB\Driver\Query
, eventualmente insieme alle opzioni relative alle proiezioni.
Estendiamo l'esempio visto fin qui al caso in cui volessimo ottenere soltanto i primi 5 risultati, ordinati in ordine ascendente secondo il campo model:
$filter = [ 'name' => 'Fiat' ];
$options = [ 'projection' => ['_id' => 0], 'sort' => [ 'model' => 1], 'limit' => 5 ];
$query = new MongoDB\Driver\Query($filter, $options);
Otterremo così 5 entry con il campo name valorizzato con la stringa Fiat, ordinate in ordine ascendente base al campo model; il campo _id sarà inoltre scartato dall'operazione di proiezione.
Scrivere i dati
Non resta a questo punto che impare ad effettuare le operazioni di scrittura sul database. A tale scopo, utilizzeremo il metodo executeBulkWrite()
della classe MongoDB\Driver\Manager
. Vediamo subito un esempio:
<?php
try {
$mng = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$bulk = new MongoDB\Driver\BulkWrite();
$doc = ['_id' => new MongoDB\BSON\ObjectID(), 'name' => 'Toyota', 'price' => 26700];
$bulk->insert($doc);
$bulk->update(['name' => 'Audi'], ['$set' => ['price' => 52000]]);
$bulk->delete(['name' => 'Hummer']);
$mng->executeBulkWrite('testdb.cars', $bulk);
} catch (MongoDB\Driver\Exception\Exception $e) {
//Errore
}
?>
L'oggetto $bulk
, istanza di MongoDB\Driver\BulkWrite
, permette di effettuare una o più operazioni di scrittura di dati sul database. Nel nostro caso, lo utilizziamo per effettuare prima un inserimento, poi un aggiornamento ed infine una eliminazione.
Innanzitutto, definiamo un nuovo documento $doc
come array associativo, che utilizzeremo in un'operazione di inserimento, specificata mediante il metodo insert()
dell'oggetto $bulk
. A seguire, il metodo update()
è utilizzato per aggiornare tutte le entry con il campo name impostato a Audi, affinchè il campo price di tali entry venga valorizzato a 52000. Infine, il metodo delete()
rimuove tutte le entry per le quali il campo name sia valorizzato a Hummer.
Si noti che l'esecuzione dei metodi insert()
, update()
e delete()
, fino a questo punto, si è limitata a "mettere in coda" l'esecuzioni di tali operazioni. Il motore di MongoDB sarà effettivamente chiamato ad eseguire tale coda di operazioni solo quando verrà eseguito il metodo executeBulkWrite()
, mediante il quale specifichiamo la collection su cui le operazioni devono essere eseguire (primo parametro) e le operazioni da effettuare (secondo parametro, ovvero nient'altro che l'oggetto $bulk
).