This is the 10gen-supported PHP driver for MongoDB.
Here's a quick code sample that connects, inserts documents, queries for documents, iterates through query results, and disconnects from MongoDB. There are more details on each step in the tutorial below.
<?php
// connect
$m = new Mongo();
// select a database
$db = $m->comedy;
// select a collection (analogous to a relational database's table)
$collection = $db->cartoons;
// add a record
$obj = array( "title" => "Calvin and Hobbes", "author" => "Bill Watterson" );
$collection->insert($obj);
// add another record, with a different "shape"
$obj = array( "title" => "XKCD", "online" => true );
$collection->insert($obj);
// find everything in the collection
$cursor = $collection->find();
// iterate through the results
foreach ($cursor as $obj) {
echo $obj["title"] . "\n";
}
?>
This would output:
Calvin and Hobbes XKCD
To connect to the database server, use one of the following:
<?php
$connection = new Mongo(); // connects to localhost:27017
$connection = new Mongo( "example.com" ); // connect to a remote host (default port)
$connection = new Mongo( "example.com:65432" ); // connect to a remote host at a given port
?>
The manual chapter on connecting covers different types of connections.
The API documentation on the Mongo class and Mongo::__construct() give a comprehensive look at all possible options with a number of examples.
To select a database, use:
<?php
$db = $connection->dbname;
?>
<?php
$db = $connection->mybiglongdbname;
// do some stuff
$db = $connection->mybiglongdbnme;
// now connected to a different database!
?>
The API documentation on the MongoDB class contains more information about database objects.
Getting a collection has the same syntax as getting a database:
<?php
$db = $connection->baz;
$collection = $db->foobar;
// or, more succinctly
$collection = $connection->baz->foobar;
?>
The API documentation on the MongoCollection class contains more information about collection objects.
Associative arrays are the basic object that can be saved to a collection in the database. A somewhat random "document" might be:
<?php
$doc = array( "name" => "MongoDB",
"type" => "database",
"count" => 1,
"info" => (object)array( "x" => 203, "y" => 102),
"versions" => array("0.9.7", "0.9.8", "0.9.9")
);
?>
To insert this document, use MongoCollection::insert():
<?php
$collection->insert( $doc );
?>
The API documentation on MongoCollection::insert() contains more information about inserting data.
To show that the document we inserted in the previous step is there, we can do a simple MongoCollection::findOne() operation to get a single document from the collection. This method is useful when there only is one document matching the query or you are only interested in one result.
<?php
$obj = $collection->findOne();
var_dump( $obj );
?>
array(5) { ["_id"]=> object(MongoId)#6 (0) { } ["name"] string(7) "MongoDB" ["type"]=> string(8) "database" ["count"]=> int(1) ["info"]=> array (2) { ["x"]=> int(203) ["y"]=> int(102) } ["versions"] array(3) { [0]=> string(5) "0.9.7" [1]=> string(5) "0.9.8" [2]=> string(5) "0.9.9" } }
Note the _id field has been added automatically to your document. _id is the "primary key" field that is automatically populate for almost all documents in MongoDB.
The API documentation on MongoCollection::findOne() contains more information about finding data.
In order to do more interesting things with queries, let's add multiple simple documents to the collection. These documents will just be
<?php
array( "i" => value );
?>
<?php
for($i=0; $i<100; $i++) {
$collection->insert( array( "i" => $i ) );
}
?>
Notice that we can insert arrays with different key sets into the same collection. This aspect is what we mean when we say that MongoDB is "schema-free".
Now that we've inserted 101 documents (the 100 we did in the loop, plus the first one), we can check to see if we have them all using the MongoCollection::count() method.
<?php
echo $collection->count();
?>
In order to get all the documents in the collection, we will use MongoCollection::find(). The find() method returns a MongoCursor object which allows us to iterate over the set of documents that matched our query. So to query all of the documents and print them out:
<?php
$cursor = $collection->find();
foreach ($cursor as $id => $value) {
echo "$id: ";
var_dump( $value );
}
?>
The API documentation on MongoCollection::find() contains more information about finding data.
We can create a query to pass to the MongoCollection::find() method to get a subset of the documents in our collection. For example, if we wanted to find the document for which the value of the "i" field is 71, we would do the following:
<?php
$query = array( "i" => 71 );
$cursor = $collection->find( $query );
while( $cursor->hasNext() ) {
var_dump( $cursor->getNext() );
}
?>
array(2) { ["_id"]=> object(MongoId)#6 (0) { } ["i"]=> int(71) ["_ns"]=> "testCollection" }
We can use the query to get a set of documents from our collection. For example, if we wanted to get all documents where "i" > 50, we could write:
<?php
$query = array( "i" => array( '$gt' => 50 ) ); //note the single quotes around '$gt'
$cursor = $coll->find( $query );
while( $cursor->hasNext() ) {
var_dump( $cursor->getNext() );
}
?>
<?php
$query = array( "i" => array( "\$gt" => 20, "\$lte" => 30 ) );
$cursor = $coll->find( $query );
while( $cursor->hasNext() ) {
var_dump( $cursor->getNext() );
}
?>
mongo.cmd = ":"
<?php
$query = array( "i" => array( ":gt" => 20, ":lte" => 30 ) );
?>
MongoDB supports indexes, and they are very easy to add on a collection. To create an index, you specify the field name and direction: ascending (1) or descending (-1). The following creates an ascending index on the "i" field:
<?php
$coll->ensureIndex( array( "i" => 1 ) ); // create index on "i"
$coll->ensureIndex( array( "i" => -1, "j" => 1 ) ); // index on "i" descending, "j" ascending
?>
If you are getting "writing more" shown at random places on the screen, it's a MongoDB connector bug in 1.0.5.
Bug report: http://jira.mongodb.org/browse/PHP-91
Update to the latest connector driver and it should go away.
please note that if you need to re-index a numeric array after and unset by offset and preserve order array_merge with only one argument will output an array keyed sequentially
<?php
$arr = array(1,2,3,4,5);
unset($arr[2]);
var_dump($arr);
$arr = array_merge($arr);
var_dump($arr);
?>
--output--
array(4) {
[0]=>
int(1)
[1]=>
int(2)
[3]=>
int(4)
[4]=>
int(5)
}
array(4) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(4)
[3]=>
int(5)
}
Make sure array keys consecutive before inserting. As of 1.0.6 driver, the following will end up as an object of key:value pairs, instead of an array, because it's trying to maintain the 0 and 2 keys:
$array = array('a', 'b', 'c');
unset($array[1]);
$document = array(
'embedded' => $array,
);
// assuming local
$mongo = new Mongo();
$mongo->test->test->insert($document);
mongodb result:
{ "_id" : ObjectId(...), "embedded" : { "0" : "a", "2" : "c" } }
This is bad if you plan on indexing the embedded property as an array because objects and arrays are indexed differently.
Whether the behaviour will change or not, this is logged here: http://jira.mongodb.org/browse/PHP-104
If you know about it, it's not major, just use a sort() before inserting, or use array_* methods to remove elements instead of unset() -- anything that will re-adjust keys.