Getting documents from MongoDB collections with PHP
We have a MongoDB server running as a windows service on the same machine as our web server. Over time, this MongoDB server had been listening on port 33333 to help us remember information that we had collected about our friends.
As time passes, our memory can hardly rival that of our MongoDB server, which was designed to help us recollect information efficiently. This post documents some proof of concept that I did for querying documents from MongoDB collection via the PHP driver.
Information structure of our friends
While MongoDB can help us remember information about our friends, we need to remember where had we instructed our MongoDB server to keep information about our friends and the document structure for such information.
Those are not hard to remember. We had constantly instructed our MongoDB server to store documents about our friends in the friend collection within the contactDb database. These documents are structured in the following format:
<?php $friend = array( 'name' => '<name>', 'birthday' => '<dd-mm-yyyy>', 'email' => '<name@example.com>', 'likes' => array('<item1>', '<item2>', '<item3>', '...'), 'yearBefriended' => '<yyyy>' ); ?>
Existing data in our MongoDB database
For the sake of this post, further assume that the friend collection in our contactDb database had accumulated some documents over time. An iteration of the documents via the print_r
function produces the following output:
Array ( [name] => Mary Jane [email] => mary.jane@gmail.com [likes] => Array ( [0] => Reading [1] => Shopping [2] => Baking [3] => Swimming ) [yearBefriended] => 2004 ) Array ( [name] => Lily Jane [email] => lily.jane@gmail.com [likes] => Array ( [0] => Diving [1] => Shopping [2] => Cooking [3] => Swimming ) [yearBefriended] => 2002 ) Array ( [name] => Johnson Peter [email] => johnson.peter@outlook.com [likes] => Array ( [0] => Jogging [1] => Programming ) [yearBefriended] => 2000 ) Array ( [name] => John Jacobs [email] => john.jacobs@gmail.com ) Array ( [name] => Michael Jackson [email] => michael@singers.net [likes] => Array ( [0] => Singing [1] => Dancing ) [yearBefriended] => 2003 )
Looking at the output, it seems that we do not have much information about John Jacobs. This is fine because MongoDB will not be rigid on the schema of the data that it manages.
Main steps to query documents from MongoDB with the PHP driver
Getting documents from collections in MongoDB consists of the following steps:
- Derive an instance of
MongoCollection
that represents the MongoDB collection to find documents. - Define a search criteria array.
- Define a results filter array.
- Execute the find function of the
MongoCollection
instance. - Iterate the results using the
MongoCursor
returned from thefind
function of theMongoCollection
instance.
Derive an instance of MongoCollection that represents the MongoDB collection to find documents
<?php $connection = new Mongo('mongodb://localhost:33333'); $friendCollection = $connection->selectCollection("contactDb", "friend"); ?>
Before we can get anything out of our MongoDB server, we will have to connect to it first. We create an instance of the Mongo
class that connects to our MongoDB server. We then execute the selectionCollection
function of the Mongo
instance to retrieve an instance of the MongoCollection
class that represents the "friend"
collection in the "contactDb"
database.
Define a search criteria array
We define the search criteria via PHP associative arrays. The field names will form the key parts and arrays or literals will form the value parts. For example, to search for Mary Jane's information, we define the following array as the search criteria:
<?php $criteria = array( 'name' => 'Mary Jane' ); ?>
Apart from this simple search criteria, we can also specify other types of search criteria to get documents from our MongoDB server.
Define a results filter array
<?php $filter = array( '_id' => 0, 'email' => 1, 'likes' => 1, 'name' => 1, 'yearBefriended' => 1 ); ?>
Like the search criteria array, we define the filter array as an associative array.
The filter array will tell MongoDB what key/value pairs to return for documents that match the search criteria specified.
A non-zero value paired with a key will indicate that we want to see value(s) referenced by the key within the returned documents, where possible.
Note that apart from the _id key having a different visibility state, our MongoDB server currently do not entertain mixed filters. That is we can have this:
<?php $filter = array( '_id' => 0, 'email' => 1, 'likes' => 1, 'name' => 1, 'yearBefriended' => 1 ); ?>
Or this:
<?php $filter = array( '_id' => 1, 'email' => 0, 'likes' => 0, 'name' => 0, 'yearBefriended' => 0 ); ?>
But not this:
<?php $filter = array( '_id' => 0, 'email' => 1, 'likes' => 0, 'name' => 1, 'yearBefriended' => 0 ); ?>
In short, we either submit an array of fields to exclude or or an array of fields to include, but not both.
Execute the find function of the MongoCollection instance
<?php $resultsCursor = $friendCollection->find($criteria, $filter); ?>
Once we have our search criteria and filter list, we call the find
function of our MongoCollection
instance ($friendCollection
) to find the documents that we desire. By doing so, we get an instance of MongoCursor
which we can use to iterate the results returned by our MongoDB server.
Note that since parameters to the find
function are optional, we could call the find
function with either a search criteria array or none at all.
When we call the find
function with only a search criteria array, we get matching documents with all their fields.
On the other hand, when we call the find
function without any parameters, we get a full listing of all the documents in the collection with all their fields.
Iterate the results using the MongoCursor returned from the find function of the MongoCollection instance
<?php echo '<pre>'; while ($resultsCursor->hasNext()) { $friend = $cursor->getNext(); print_r($friend); echo PHP_EOL; } echo '</pre>' ?>
We make use of the hasNext
function and the getNext
function of the MongoCursor
instance to iterate through the search results.
The hasNext
function checks whether there is a document to grab from the results, while the getNext
function grabs one document from the results and move the cursor to the next document. We put these two functions together with the print_r
within a while loop to output the contents of documents that matched the search criteria and search filter.
Some types of search criteria
The following section is a listing of MongoDB query facilities that I had tried out using the PHP driver. For the sake of brevity, I list only the search criteria arrays and the corresponding results. The results output is produced via the same set of codes as discussed in the earlier sections.
Search criteria to find documents with a field value that is greater than (or equals to), less than (or equals to), not equals to another value ($gt, $lt, $gte, $lte, $ne)
For finding friends whom we befriended in a year other than 2003, via $ne
<?php
$criteria = array (
'yearBefriended' => array(
'$ne' => 2003
)
);
?>
Friends whom we befriended in a year other than 2003
Array
(
[name] => Mary Jane
[email] => mary.jane@gmail.com
[likes] => Array
(
[0] => Reading
[1] => Shopping
[2] => Baking
[3] => Swimming
)
[yearBefriended] => 2004
)
Array
(
[name] => Lily Jane
[email] => lily.jane@gmail.com
[likes] => Array
(
[0] => Diving
[1] => Shopping
[2] => Cooking
[3] => Swimming
)
[yearBefriended] => 2002
)
Array
(
[name] => Johnson Peter
[email] => johnson.peter@outlook.com
[likes] => Array
(
[0] => Jogging
[1] => Programming
)
[yearBefriended] => 2000
)
Array
(
[name] => John Jacobs
[email] => john.jacobs@gmail.com
)
<?php $criteria = array ( 'yearBefriended' => array( '$ne' => 2003 ) ); ?>
Friends whom we befriended in a year other than 2003
Array ( [name] => Mary Jane [email] => mary.jane@gmail.com [likes] => Array ( [0] => Reading [1] => Shopping [2] => Baking [3] => Swimming ) [yearBefriended] => 2004 ) Array ( [name] => Lily Jane [email] => lily.jane@gmail.com [likes] => Array ( [0] => Diving [1] => Shopping [2] => Cooking [3] => Swimming ) [yearBefriended] => 2002 ) Array ( [name] => Johnson Peter [email] => johnson.peter@outlook.com [likes] => Array ( [0] => Jogging [1] => Programming ) [yearBefriended] => 2000 ) Array ( [name] => John Jacobs [email] => john.jacobs@gmail.com )
Note that John Jacobs was listed because of the absence of a yearBefriended
field.
For finding friends whom we befriended in 2003
<?php $criteria = array ( 'yearBefriended' => 2003 ); ?>
Friend whom we befriended in 2003
Array ( [name] => Michael Jackson [email] => michael@singers.net [likes] => Array ( [0] => Singing [1] => Dancing ) [yearBefriended] => 2003 )
For finding friends whom we befriended from 2001 to 2003, via $gt and $lt
<?php $criteria = array ( 'yearBefriended' => array ( '$gt' => 2000, '$lt' => 2004 ) ); ?>
Friends whom we befriended in 2001, 2002 or 2003
Array ( [name] => Lily Jane [email] => lily.jane@gmail.com [likes] => Array ( [0] => Diving [1] => Shopping [2] => Cooking [3] => Swimming ) [yearBefriended] => 2002 ) Array ( [name] => Michael Jackson [email] => michael@singers.net [likes] => Array ( [0] => Singing [1] => Dancing ) [yearBefriended] => 2003 )
For finding friends whom we befriended in 2000, 2001, 2002, 2003 or 2004, via $gte and $lte
<?php $criteria = array ( 'yearBefriended' => array ( '$gte' => 2000, '$lte' => 2004 ) ); ?>
Friends whom we befriended in 2000, 2001, 2002, 2003 or 2004
Array ( [name] => Mary Jane [email] => mary.jane@gmail.com [likes] => Array ( [0] => Reading [1] => Shopping [2] => Baking [3] => Swimming ) [yearBefriended] => 2004 ) Array ( [name] => Lily Jane [email] => lily.jane@gmail.com [likes] => Array ( [0] => Diving [1] => Shopping [2] => Cooking [3] => Swimming ) [yearBefriended] => 2002 ) Array ( [name] => Johnson Peter [email] => johnson.peter@outlook.com [likes] => Array ( [0] => Jogging [1] => Programming ) [yearBefriended] => 2000 ) Array ( [name] => Michael Jackson [email] => michael@singers.net [likes] => Array ( [0] => Singing [1] => Dancing ) [yearBefriended] => 2003 )
Search criteria to find documents that contain or not contain a certain field ($exists)
For finding friends who told us what they like
<?php $criteria = array ( 'likes' => array('$exists' => true) ); ?>
Friends who told us what they like
Array ( [name] => Mary Jane [email] => mary.jane@gmail.com [likes] => Array ( [0] => Reading [1] => Shopping [2] => Baking [3] => Swimming ) [yearBefriended] => 2004 ) Array ( [name] => Lily Jane [email] => lily.jane@gmail.com [likes] => Array ( [0] => Diving [1] => Shopping [2] => Cooking [3] => Swimming ) [yearBefriended] => 2002 ) Array ( [name] => Johnson Peter [email] => johnson.peter@outlook.com [likes] => Array ( [0] => Jogging [1] => Programming ) [yearBefriended] => 2000 ) Array ( [name] => Michael Jackson [email] => michael@singers.net [likes] => Array ( [0] => Singing [1] => Dancing ) [yearBefriended] => 2003 )
For finding friends who did not tell us what they like
<?php $criteria = array ( 'likes' => array('$exists' => false) ); ?>
Friend who did not tell us what he likes
Array ( [name] => John Jacobs [email] => john.jacobs@gmail.com )
Search criteria to find documents with field of type array having / not having one of a list of items ($in, $nin)
For finding friends who likes swimming, via $in
<?php $criteria = array ( 'likes' => array( '$in' => array( 'Swimming' ) ) ); ?>
Friends who likes swimming
Array ( [name] => Mary Jane [email] => mary.jane@gmail.com [likes] => Array ( [0] => Reading [1] => Shopping [2] => Baking [3] => Swimming ) [yearBefriended] => 2004 ) Array ( [name] => Lily Jane [email] => lily.jane@gmail.com [likes] => Array ( [0] => Diving [1] => Shopping [2] => Cooking [3] => Swimming ) [yearBefriended] => 2002 )
For finding friends who do not tell us that they like to swim, via $nin
<?php $criteria = array ( 'likes' => array ( '$nin' => array ( 'Swimming' ) ) ); ?>
Friends who do not say that they like to swim
Array ( [name] => Johnson Peter [email] => johnson.peter@outlook.com [likes] => Array ( [0] => Jogging [1] => Programming ) [yearBefriended] => 2000 ) Array ( [name] => John Jacobs [email] => john.jacobs@gmail.com ) Array ( [name] => Michael Jackson [email] => michael@singers.net [likes] => Array ( [0] => Singing [1] => Dancing ) [yearBefriended] => 2003 )
Search criteria to find documents with field of type array having all the items in a list ($all)
For finding friends who like both swimming and cooking
<?php $criteria = array ( 'likes' => array ( '$all' => array ( 'Cooking', 'Swimming' ) ) ); ?>
Friend who likes both swimming and cooking
Array ( [name] => Lily Jane [email] => lily.jane@gmail.com [likes] => Array ( [0] => Diving [1] => Shopping [2] => Cooking [3] => Swimming ) [yearBefriended] => 2002 )
Search criteria to find documents with field matching a regular expression
For finding friends having "Jane" as his/her surname
<?php $criteria = array( 'name' => array ( '$regex' => '.*Jane' ) ); ?>
Or
<?php $criteria = array ( 'name' => new MongoRegex('/^.*Jane/') ); ?>
Friends having "Jane" as his/her surname
Array ( [name] => Mary Jane [email] => mary.jane@gmail.com [likes] => Array ( [0] => Reading [1] => Shopping [2] => Baking [3] => Swimming ) [yearBefriended] => 2004 ) Array ( [name] => Lily Jane [email] => lily.jane@gmail.com [likes] => Array ( [0] => Diving [1] => Shopping [2] => Cooking [3] => Swimming ) [yearBefriended] => 2002 )
Search criteria to match documents with any of the stated conditions ($or)
For finding friends whom we befriended in year 2000 or year 2003
<?php $criteria = array ( '$or' => array ( array ( 'yearBefriended' => 2000 ), array ( 'yearBefriended' => 2003 ) ) ); ?>
Friends whom we befriended in year 2000 or year 2003
Array ( [name] => Johnson Peter [email] => johnson.peter@outlook.com [likes] => Array ( [0] => Jogging [1] => Programming ) [yearBefriended] => 2000 ) Array ( [name] => Michael Jackson [email] => michael@singers.net [likes] => Array ( [0] => Singing [1] => Dancing ) [yearBefriended] => 2003 )
Search criteria to match documents with all of the stated conditions ($and)
For finding the Jane whom we befriended in 2002
<?php $criteria = array ( '$and' => array ( array ( 'name' => new MongoRegex('/^.*Jane/') ), array ( 'yearBefriended' => 2002 ) ) ); ?>
Or
<?php $criteria = array ( 'name' => new MongoRegex('/^.*Jane/'), 'yearBefriended' => 2002 ); ?>
The Jane whom we befriended in 2002
Array ( [name] => Lily Jane [email] => lily.jane@gmail.com [likes] => Array ( [0] => Diving [1] => Shopping [2] => Cooking [3] => Swimming ) [yearBefriended] => 2002 )