⬆️ ⬇️

Getting Started with MongoDB and PHP

Generation Next

Over the past year, there has been a small revolution in the DBMS world, associated with the emergence of schema-free (structureless) DBMS such as Apache CouchDB . In these databases, a different approach is used than in relational databases. They quickly become popular among Web developers because of their flexibility, simplicity and easy integration with modern technologies such as JSON.

This article provides a brief overview of MongoDB, one of the new generations of noncircuit DBMS, which has received much attention from developers.



Start me up

On the official website of MongoDB it is written that it is an expandable, high-performance, document-oriented database with open source. It exists under a large number of platforms and is distributed under the GNU AGPL license.

Although MongoDB is similar to CouchDB, there are serious differences between them:



The MongoDB documentation describes in detail all these (and a bit more) differences, there are also tests comparing MongoDB, CouchDB and MySQL ( another reason for holy war ).

A quick overview is over, time to download and install MongoDB. In most cases, a standard binary package is enough; it contains MongoDB and a command line client, a set of utilities for backing up, restoring, and saving and retrieving binary files. To get started, download the appropriate version for your system:

shell> cd / usr / local

shell> tar -xzvf mongodb-linux-i686-1.4.2.tgz

shell> ln -s mongodb-linux-i686-1.4.2 mongo

If you have Ubuntu, you can install MongoDB using aptitude. To do this, add the following line to /etc/apt/sources.list:

deb downloads.mongodb.org/distros/ubuntu 10.4 10gen

Then install this package using aptitude:

shell> aptitude update

shell> aptitude install mongodb-stable

When the package is installed, start the MongoDB server

shell> mkdir / usr / local / mongo / data

shell> / usr / local / mongo / bin / mongod --dbpath = / usr / local / mongo / data





Note that by default, the MongoDB server considers that data is stored in / data / db, and ends execution if it does not find this path. The --dbpath option allows you to specify another path.

You can use the command line to access the server, as shown below:

shell> / usr / local / mongo / mongo

Here's what it looks like:





You can give commands to the server, as well as in the MySQL client. Below is an example that shows the server version and available databases:

>show dbs

admin

local

>db.version()

1.4.2

>db.stats()

{

"collections" : 0,

"objects" : 0,

"dataSize" : 0,

"storageSize" : 0,

"numExtents" : 0,

"indexes" : 0,

"indexSize" : 0,

"ok" : 1

}



* This source code was highlighted with Source Code Highlighter .


')

Collecting Ideas

In the MongoDB universe, the equivalent of a table is the “collection”. Just as tables have many records, in collections there are many “documents”. These documents are represented as JSON objects, with fields and values ​​representing key-value pairs, and stored (serialized) in BSON (Binary JSON) for storage. Below is an example of one such document:

{

"OrderDate": "10-05-2010",

"OrderTotal": 468.99,

}

Since the main MongoDB element is a JSON document, and JSON supports hierarchical data, you can include one document in another. Further, since documents are serialized to BSON for storage, MongoDB can easily search for attached documents. Below is an example:

{

"OrderDate": "10-05-2010",

"OrderTotal": 468.99,

"ShipTo":

{

"Street": "17 Hill View",

"Zip": "12345",

"Country": "US"

}

}

To create a new MongoDB collection, run the client on the command line and execute the following commands that will create a collection called items "and add several documents:

  1. > db.items. insert ({name: 'eggs' , quantity: 10, price: 1.50})
  2. > db.items. insert ({name: 'bacon' , quantity: 3, price: 3.50})
  3. > db.items. insert ({name: 'tomatoes' , quantity: 30, price: 0.50})
* This source code was highlighted with Source Code Highlighter .


We continue further, add more documents as shown above. To display the full list of documents in the collection, call the find () method with no arguments:

  1. > db.items.find ({})
  2. {"_id": ObjectId ("4bea15293302000000006dcf"), "name": "eggs", "quantity": 10, "price": 1.5}
  3. {"_id": ObjectId ("4bea15463302000000006dd0"), "name": "bacon", "quantity": 3, "price": 3.5}
  4. {"_id": ObjectId ("4bea15523302000000006dd1"), "name": "tomatoes", "quantity": 30, "price": 0.5
  5. }
* This source code was highlighted with Source Code Highlighter .


Notice that each document has a special '_id' key. When you write a new document to the collection, MongoDB automatically adds a unique identifier to each document. This identifier can be used to retrieve or modify a document, it is a kind of auto-increment key in relational databases.

To display a list of documents by any criteria, add this criterion (as a JSON object) to the find () method. Below is an example showing entries with a quantity greater than 9 and a price less than 1:

  1. > db.items.find ({quantity: {$ gt: 9}, price: {$ lt: 1}})
  2. {"_id": ObjectId ("4bea15523302000000006dd1"), "name": "tomatoes", "quantity": 30, "price": 0.5
  3. }
* This source code was highlighted with Source Code Highlighter .


Now let's try to write something in php!



Hooking things up

MongoDB support in PHP is implemented through an extension that provides an API for accessing MongoDB collections. This extension is developed by Kristina Chodorow and is available for free in PECL under the Apache License. The extension is stable and allows you to perform most tasks related to accessing and using the MongoDB database from applications written in PHP.

To use this extension, install it using the standard pecl command.

shell> pecl install mongo

Or you can download the source code, compile it into a downloadable PHP module:

shell> tar -xzvf mongo-1.0.7.tar.gz

shell> cd mongo-1.0.7

shell> phpize

shell> ./configure

shell> make

shell> make install

You now have a PHP downloadable module called mongo.so, which is in the standard PHP module directory. Enable this extension in php.ini, reload the Web server and check the activity of this extension with the phpinfo () command:





Now let's see what we can do using this extension.

  1. <? php
  2. try {
  3. // open connection to MongoDB server
  4. $ conn = new Mongo ( 'localhost' );
  5. // access database
  6. $ db = $ conn-> test;
  7. // access collection
  8. $ collection = $ db-> items;
  9. // execute query
  10. // retrieve all documents
  11. $ cursor = $ collection-> find ();
  12. // iterate through the result set
  13. // print each document
  14. echo $ cursor-> count (). 'document (s) found. <br/> ' ;
  15. foreach ($ cursor as $ obj) {
  16. echo 'Name:' . $ obj [ 'name' ]. '<br/>' ;
  17. echo 'Quantity:' . $ obj [ 'quantity' ]. '<br/>' ;
  18. echo 'Price:' . $ obj [ 'price' ]. '<br/>' ;
  19. echo '<br/>' ;
  20. }
  21. // disconnect from server
  22. $ conn-> close ();
  23. } catch (MongoConnectionException $ e) {
  24. die ( 'Error connecting to MongoDB server' );
  25. } catch (MongoException $ e) {
  26. die ( 'Error:' . $ e-> getMessage ());
  27. }
  28. ?>
* This source code was highlighted with Source Code Highlighter .


At the beginning of this script, a new Mongo object is initialized, to the constructor of which the information necessary to establish a connection with the MongoDB server (in the example host name) is transferred. This object is used for all subsequent interactions with the MongoDB server.

The next step is to gain access to the database. This can be done using the selectDB () method or, more simply, using the magic call method, access the database as an object property. Once the database is accessed, it will not be difficult to access the collection using the selectCollection () method or by using the magic call method, accessing the collection as a property. Collections are represented as MongoCollection objects.

Each MongoCollection object has a find () method that can be used to execute queries. The method takes as arguments two arrays: an array of query parameters and an array of fields that should be obtained as a result of the response to the query. The return value is a cursor represented by an object of type MongoCursor object. The MongoCursor type implements the (implement) Iterator pattern, so it is fairly easy to run through the entire returned set using foreach (). The MongoCursor type contains a count () method that returns the number of entries.

The Mongo PHP extension supports the exception model implemented in PHP 5.x and defines 5 types of exceptions: MongoConnectionException for connection errors, MongoCursorException and MongoCursorTimeoutException for request errors; MongoGridFSException for file interaction errors; and MongoException for all other errors. In the previous example, it would be a good idea to enclose the code in a try / catch block.

Below is an example of the output of the previous example:





Addition And Subtraction

Adding a new document to the collection is quite simple. See the following example:

<?php

try {

// open connection to MongoDB server

$conn = new Mongo( 'localhost' );



// access database

$db = $conn->test;



// access collection

$collection = $db->items;



// insert a new document

$item = array(

'name' => 'milk' ,

'quantity' => 10,

'price' => 2.50,

'note' => 'skimmed and extra tasty'

);

$collection->insert($item);

echo 'Inserted document with ID: ' . $item[ '_id' ];



// disconnect from server

$conn->close();

} catch (MongoConnectionException $e) {

die( 'Error connecting to MongoDB server' );

} catch (MongoException $e) {

die( 'Error: ' . $e->getMessage());

}

?>



* This source code was highlighted with Source Code Highlighter .


To add a new document to the collection, create a new array containing a key-value pair that you want to insert (the mechanism also supports nested arrays that are converted into embedded documents) and pass this array to the insert method of an object of type MongoCollection. This method will add a document to the collection and calculate the value of '_id' (unique document identifier), which will be added to the original array. This identifier is represented by a special type of MongoId, which is a hexadecimal representation of the identifier. Therefore, you can easily get the ID of the document without making an additional request.

Below is an example:





The document is removed from the collection by the remove () method, which takes an array of criteria as parameters, and removes all documents that meet these criteria. Normally remove () returns a Boolean value (true or false); However, if you pass a special 'safe' argument as the second argument, you can get an array with a large amount of information, including the number of deleted documents. Below is an example:

<?php

try {

// open connection to MongoDB server

$conn = new Mongo( 'localhost' );



// access database

$db = $conn->test;



// access collection

$collection = $db->items;



// remove a document

$criteria = array(

'name' => 'milk' ,

);

$r = $collection->remove($criteria, array( 'safe' => true ));

echo 'Removed ' . $r[ 'n' ] . ' document(s).' ;



// disconnect from server

$conn->close();

} catch (MongoConnectionException $e) {

die( 'Error connecting to MongoDB server' );

} catch (MongoException $e) {

die( 'Error: ' . $e->getMessage());

}

?>



* This source code was highlighted with Source Code Highlighter .


It is also possible to delete a document using its id. However, the object of the MongoId method is passed to the remove () method, not the PHP string. Below is an example:

<?php

try {

// open connection to MongoDB server

$conn = new Mongo( 'localhost' );



// access database

$db = $conn->test;



// access collection

$collection = $db->items;



// remove a document by ID

$criteria = array(

'_id' => new MongoId( '4bea96b400f4784c0a070000' ),

);

$collection->remove($criteria);

echo 'Removed document with ID: ' . $criteria[ '_id' ];



// disconnect from server

$conn->close();

} catch (MongoConnectionException $e) {

die( 'Error connecting to MongoDB server' );

} catch (MongoException $e) {

die( 'Error: ' . $e->getMessage());

}

?>



* This source code was highlighted with Source Code Highlighter .


The document is updated using the save () method, as shown below:

<?php

try {

// open connection to MongoDB server

$conn = new Mongo( 'localhost' );



// access database

$db = $conn->test;



// access collection

$collection = $db->items;



// retrieve existing document

$criteria = array(

'name' => 'eggs' ,

);

$doc = $collection->findOne($criteria);



// update document with new values

// save back to collection

$doc[ 'name' ] = 'apples' ;

$doc[ 'quantity' ] = 35;

$doc[ 'note' ] = 'green apples taste sooooo good!' ;

$collection->save($doc);



// disconnect from server

$conn->close();

} catch (MongoConnectionException $e) {

die( 'Error connecting to MongoDB server' );

} catch (MongoException $e) {

die( 'Error: ' . $e->getMessage());

}

?>



* This source code was highlighted with Source Code Highlighter .


Note that if findOne () did not return anything, the save () call will add a new document.

Asking Questions

When it comes to query execution, MongoDB offers quite flexible tools. You have already seen the find () method, which returns a collection of documents matching the search criteria. There is also a findOne () method that returns a single document. You can use many search criteria — just pass an array as find criteria to find () or findOne (), and MongoDB will apply all of these criteria with the AND modifier.

Below is an example:

<?php

try {

// open connection to MongoDB server

$conn = new Mongo( 'localhost' );



// access database

$db = $conn->test;



// access collection

$collection = $db->items;



// formulate AND query

$criteria = array(

'quantity' => 30,

'price' => 0.5

);



// retrieve only 'name' and 'price' keys

$fields = array( 'name' , 'price' );



// execute query

$cursor = $collection->find($criteria, $fields);



// iterate through the result set

// print each document

echo $cursor->count() . ' document(s) found. <br/>' ;

foreach ($cursor as $obj) {

echo 'Name: ' . $obj[ 'name' ] . '<br/>' ;

echo 'Price: ' . $obj[ 'price' ] . '<br/>' ;

echo '<br/>' ;

}



// disconnect from server

$conn->close();

} catch (MongoConnectionException $e) {

die( 'Error connecting to MongoDB server' );

} catch (MongoException $e) {

die( 'Error: ' . $e->getMessage());

}

?>



* This source code was highlighted with Source Code Highlighter .


MongoDB also supports a large number of conditional and logical operators for creating complex queries. Plus, regular expression support. Below is an example that displays all entries with a number between 10 and 50 and whose names end with 'es':

<?php

try {

// open connection to MongoDB server

$conn = new Mongo( 'localhost' );



// access database

$db = $conn->test;



// access collection

$collection = $db->items;



// formulate complex query

$criteria = array(

'quantity' => array(

'$gt' => 10,

'$lt' => 50

),

'name' => new MongoRegex( '/es$/i' )

);



// execute query

$cursor = $collection->find($criteria);



// iterate through the result set

// print each document

echo $cursor->count() . ' document(s) found. <br/>' ;

foreach ($cursor as $obj) {

echo 'Name: ' . $obj[ 'name' ] . '<br/>' ;

echo 'Quantity: ' . $obj[ 'quantity' ] . '<br/>' ;

echo 'Price: ' . $obj[ 'price' ] . '<br/>' ;

echo '<br/>' ;

}



// disconnect from server

$conn->close();

} catch (MongoConnectionException $e) {

die( 'Error connecting to MongoDB server' );

} catch (MongoException $e) {

die( 'Error: ' . $e->getMessage());

}

?>



* This source code was highlighted with Source Code Highlighter .


How will it look like:





You can also change the number of returned documents or sort them by the required key using the limit () and sort () methods. Below is an example:

<?php

try {

// open connection to MongoDB server

$conn = new Mongo( 'localhost' );



// access database

$db = $conn->test;



// access collection

$collection = $db->items;



// execute query

// sort by price

// limit to 3 documents

$cursor = $collection->find();

$cursor->sort(array( 'price' => 1))->limit(3);



// iterate through the result set

// print each document

echo $cursor->count() . ' document(s) found. <br/>' ;

foreach ($cursor as $obj) {

echo 'Name: ' . $obj[ 'name' ] . '<br/>' ;

echo 'Quantity: ' . $obj[ 'quantity' ] . '<br/>' ;

echo 'Price: ' . $obj[ 'price' ] . '<br/>' ;

echo '<br/>' ;

}



// disconnect from server

$conn->close();

} catch (MongoConnectionException $e) {

die( 'Error connecting to MongoDB server' );

} catch (MongoException $e) {

die( 'Error: ' . $e->getMessage());

}

?>



* This source code was highlighted with Source Code Highlighter .


By the way, if you go to find out how inside MongoDB executes a request, you can use the explain () method of the MongoCursor object to “look inside” the query processing system, much like the MySQL EXPLAIN command. Below is an example and output:

<?php

try {

// open connection to MongoDB server

$conn = new Mongo( 'localhost' );



// access database

$db = $conn->test;



// access collection

$collection = $db->items;



// execute and explain query

$criteria = array(

'quantity' => array(

'$gt' => 10,

'$lt' => 50

),

'name' => new MongoRegex( '/es$/i' )

);

$cursor = $collection->find($criteria);

$cursor->sort(array( 'price' => 1))->limit(3);

print_r($cursor->explain());



// disconnect from server

$conn->close();

} catch (MongoConnectionException $e) {

die( 'Error connecting to MongoDB server' );

} catch (MongoException $e) {

die( 'Error: ' . $e->getMessage());

}

?>



* This source code was highlighted with Source Code Highlighter .






Rank and file

In addition to documents, MongoDB also supports binary data. Binary data up to 4 MB can be stored in a regular document, and data (files) that are larger than this size can be saved using a small thing called GridFS .

GridFS is a specification that describes splitting and saving large files in MongoDB. Normally, GridFS uses two collections: the 'files' collection, which caches metadata about each file, and the 'chunks' collection, which stores data divided into chunks. Each file in the 'files' collection has a unique identifier, similar to the identifiers of other documents stored in MongoDB; This identifier can be used to get or modify the file.



The MongoDB PECL extension provides a set of MongoGridFS classes that can be used to interact with files saved using GridFS. Each file is represented by an instance of the MongoGridFSFile class, and each MongoGridFS object provides methods for adding, deleting, and searching for these files.



For better understanding, consider the following example, which illustrates the process of adding an image to MongoDB:

<?php

try {

// open connection to MongoDB server

$conn = new Mongo( 'localhost' );



// access database

$db = $conn->test;



// get GridFS files collection

$gridfs = $db->getGridFS();



// store file in collection

$id = $gridfs->storeFile( '/tmp/img_2312.jpg' );

echo 'Saved file with ID: ' . $id;



// disconnect from server

$conn->close();

} catch (MongoConnectionException $e) {

die( 'Error connecting to MongoDB server' );

} catch (MongoException $e) {

die( 'Error: ' . $e->getMessage());

}

?>



* This source code was highlighted with Source Code Highlighter .


At the beginning of the example, an instance of the MongoGridFS class is obtained using the MongoDB class's getGridFS () method, and then stored by the storeFile () method in MongoDB. If you run this example, and then look at the contents of your database, you will see two new collections 'fs.files' and 'fs.chunks'. If you look a little deeper into the 'fs.files' collection, then you will see the file you’ve added.

> show collections

fs.chunks

fs.files

items

system.indexes

> db.fs.files.find()

{ "_id" : ObjectId( "4beaa34f00f4784c0a300000" ), "filename" : "/tmp/img_2312.jpg" , "uploadDate" : "Wed May 12 2010 18:17:11 GMT+0530 (India Standard Time)" , "length" : 11618, "chunkSize" : 262144, "md5" : "e66b9a33c7081ae2e4fff4c37f1f756b" }



* This source code was highlighted with Source Code Highlighter .


As an alternative to the storeFile (), there is a method called storeUpload (), which is designed to be used in conjunction with file loading using PHP. Using this feature is very easy: pass the name of the file upload field to the storeUpload in the form, and MongoDB will do everything itself. You can also pass the file name as the second argument.

Below is a small example:

<html>

<head></head>

<body>

<form method= "post" enctype= "multipart/form-data" >

Select file for upload:

<input type= "file" name= "f" />

<input type= "submit" name= "submit" />

</form>

<?php

if (isset($_POST[ 'submit' ])) {

try {

// open connection to MongoDB server

$conn = new Mongo( 'localhost' );



// access database

$db = $conn->test;



// get GridFS files collection

$gridfs = $db->getGridFS();



// check uploaded file

// store uploaded file in collection and display ID

if (is_uploaded_file($_FILES[ 'f' ][ 'tmp_name' ])) {

$id = $gridfs->storeUpload( 'f' );

echo 'Saved file with ID: ' . $id;

} else {

throw new Exception( 'Invalid file upload' );

}



// disconnect from server

$conn->close();

} catch (MongoConnectionException $e) {

die( 'Error connecting to MongoDB server' );

} catch (Exception $e) {

die( 'Error: ' . $e->getMessage());

}

}

?>

</body>

</html>



* This source code was highlighted with Source Code Highlighter .


Having a file in the database, how to get it back? Of course, using the document ID to retrieve the file (MongoGridFS is the inheritor of the MongoCollection, so you can use find () and findOne ()) as an object of the MongoGridFSFile class, and then write it to disk using the write () method, or output it to or using getBytes (). If you use browser output, do not forget to add the necessary header (header)!

Below is an example:

<?php

try {

// open connection to MongoDB server

$conn = new Mongo( 'localhost' );



// access database

$db = $conn->test;



// get GridFS files collection

$grid = $db->getGridFS();



// retrieve file from collection

$file = $grid->findOne(array( '_id' => new MongoId( '4beaa34f00f4784c0a300000' )));



// send headers and file data

header( 'Content-Type: image/jpeg' );

echo $file->getBytes();

exit;



// disconnect from server

$conn->close();

} catch (MongoConnectionException $e) {

die( 'Error connecting to MongoDB server' );

} catch (MongoException $e) {

die( 'Error: ' . $e->getMessage());

}

?>



* This source code was highlighted with Source Code Highlighter .




Boys And Their Toys

Although the PECL MongoDB extension offers quite convenient methods for working with MongoDB, you may need a higher level of abstraction - say, for example, if you are trying to integrate MongoDB into an existing application (framework-based application). In this case, you can use Morph , the high-level library for MongoDB, which is available for free under the GNU GPL license.



Morph is written as an ActiveRecord template that allows you to create a description of a MongoDB object, extending the main Morph_Object class. These instances of the Morph_Object class are reflected directly into MongoDB documents and have the same properties and methods by which you can work using standard object notation.



To illustrate, suppose you want to create a toy database. Common attributes include name, description, age suitability, gender suitability and price. You can present all this information as an object of the Morph_Object class:

<?php

class Toy extends Morph_Object {



public function __construct($id = null )

{

parent::__construct($id);

$ this ->addProperty( new Morph_Property_String( 'name' ))

->addProperty( new Morph_Property_String( 'colors' ))

->addProperty( new Morph_Property_Integer( 'minAge' ))

->addProperty( new Morph_Property_Integer( 'maxAge' ))

->addProperty( new Morph_Property_Enum( 'gender' , null , array( 'boys' , 'girls' , 'both' )))

->addProperty( new Morph_Property_Float( 'price' ));

}

}

?>



* This source code was highlighted with Source Code Highlighter .


Now you can create a new document using this template using an object of the Toy class, set properties and write it using the save () method. Below is an example:

<?php

require_once 'Morph.phar' ;



// initialize MongoDB connection

$mongo = new Mongo( 'localhost' );



// select database for storage

$storage = Morph_Storage::init($mongo->selectDb( 'test' ));



// create object and set properties

$toy = new Toy();

$toy->name = 'Ride Along Fire Engine' ;

$toy->colors = 'red,yellow' ;

$toy->minAge = '2' ;

$toy->maxAge = '4' ;

$toy->gender = 'both' ;

$toy->price = 145.99;



// save to database

$storage->save($toy);

echo 'Document saved with ID: ' . $toy->id();

?>



* This source code was highlighted with Source Code Highlighter .


Also, you can get an object by its identifier, update it and save it back.

<?php

require_once 'Morph.phar' ;



// initialize MongoDB connection

$mongo = new Mongo( 'localhost' );



// select database for storage

$storage = Morph_Storage::init($mongo->selectDb( 'test' ));



// create object and set properties

$toy = new Toy();

$toy->loadById( '5421d0b9fc6217c5bb929baa14a97e08' );

$toy->name = 'Jumping Squid' ;

$toy->colors = 'red,orange,green,blue,yellow' ;

$toy->minAge = '2' ;

$toy->maxAge = '10' ;

$toy->gender = 'boys' ;

$toy->price = 22.99;



// save to database

$storage->save($toy);

echo 'Document saved with ID: ' . $toy->id();

?>



* This source code was highlighted with Source Code Highlighter .




All these examples illustrate - MongoDB provides a reliable, feature-rich implementation of a schema-free DBMS. Accessibility for various platforms, easy integration with PHP and other languages, and extensive documentation (plus very cool online experimentation) make MongoDB ideal for developing modern, document-oriented databases.

Source: https://habr.com/ru/post/103699/



All Articles