6 min read
The following book excerpt is taken from the title Mastering MongoDB 3.x written by Alex Giamas. This book covers the fundamental as well as advanced tasks related to working with MongoDB.

There are two ways to connect your data to MongoDB. The first is using the driver for your programming language. The second is by using an ODM (Object Document Mapper) layer to map your model objects to MongoDB in a transparent way. In this post, we will cover both methods using two of the most popular languages for web application development:

  • Python, using the official MongoDB low level driver, PyMongo, and
  • PHP, using the official PHP driver for MongoDB

Connect using Python

Installing PyMongo can be done using pip or easy_install:

python -m pip install pymongo

python -m easy_install pymongo

Then in our class we can connect to a database:

>>> from pymongo import MongoClient

>>> client = MongoClient()

Connecting to a replica set needs a set of seed servers for the client to find out what the primary, secondary, or arbiter nodes in the set are:


client =

pymongo.MongoClient('mongodb://user:[email protected]:p1,node2:p2/?replicaSet=rs name')

Using the connection string URL we can pass a username/password and replicaSet name all in a single string. Some of the most interesting options for the connection string URL are presented later.

Connecting to a shard requires the server host and IP for the mongo router, which is the mongos process.

PyMODM ODM

Similar to Ruby’s Mongoid, PyMODM is an ODM for Python that follows closely on Django’s built-in ORM. Installing it can be done via pip:

pip install pymodm

Then we need to edit settings.py and replace the database engine with a dummy database:

DATABASES = {

'default': {

'ENGINE': 'django.db.backends.dummy'

}

}

And add our connection string anywhere in settings.py:

from pymodm import connect

connect("mongodb://localhost:27017/myDatabase", alias="MyApplication")

Here we have to use a connection string that has the following structure:

mongodb://[username:[email protected]]host1[:port1][,host2[:port2],...[,hostN[:port

N]]][/[database][?options]]

Options have to be pairs of name=value with an & between each pair. Some interesting pairs are:

Mastering MongoDB

Model classes need to inherit from MongoModel. A sample class will look like this:

from pymodm import MongoModel, fields

class User(MongoModel):

email = fields.EmailField(primary_key=True)

first_name = fields.CharField()

last_name = fields.CharField()

This has a User class with first_name, last_name, and email fields where email is the primary field.

Inheritance with PyMODM models

Handling one-one and one-many relationships in MongoDB can be done using references or embedding. This example shows both ways: references for the model user and embedding for the comment model:

from pymodm import EmbeddedMongoModel, MongoModel, fields

class Comment(EmbeddedMongoModel):

author = fields.ReferenceField(User)

content = fields.CharField()

class Post(MongoModel):

title = fields.CharField()

author = fields.ReferenceField(User)

revised_on = fields.DateTimeField()

content = fields.CharField()

comments = fields.EmbeddedDocumentListField(Comment)

Connecting with PHP

The MongoDB PHP driver was rewritten from scratch two years ago to support the PHP 5, PHP 7, and HHVM architectures. The current architecture is shown in the following diagram:

Connecting with PHP

Currently we have official drivers for all three architectures with full support for the underlying functionality.

Installation is a two-step process. First we need to install the MongoDB extension. This extension is dependent on the version of PHP (or HHVM) that we have installed and can be done using brew in Mac. For example with PHP 7.0:

brew install php70-mongodb

Then, using composer (a widely used dependency manager for PHP):

composer require mongodb/mongodb

Connecting to the database can then be done by using the connection string URI or by passing an array of options. Using the connection string URI we have:

$client = new MongoDBClient($uri = 'mongodb://127.0.0.1/', array

$uriOptions = [], array $driverOptions = [])

For example, to connect to a replica set using SSL authentication:

$client = new

MongoDBClient('mongodb://myUsername:[email protected],rs2.example.com/?ssl=true&replicaSet=myReplicaSet&authSource=admin');

Or we can use the $uriOptions parameter to pass in parameters without using the connection string URL, like this:

$client = new MongoDBClient(

'mongodb://rs1.example.com,rs2.example.com/'

[

'username' => 'myUsername',

'password' => 'myPassword',

'ssl' => true,

'replicaSet' => 'myReplicaSet',

'authSource' => 'admin',

],

);

The set of $uriOptions and the connection string URL options available are analogous to the ones used for Ruby and Python.

Doctrine ODM

Laravel is one of the most widely used MVC frameworks for PHP, similar in architecture to  Django and Rails from the Python and Ruby worlds respectively. We will follow through configuring our models using a stack of Laravel, Doctrine, and MongoDB. This section assumes that Doctrine is installed and working with Laravel 5.x.

Doctrine entities are POPO (Plain Old PHP Objects) that, unlike Eloquent, Laravel’s default ORM doesn’t need to inherit from the Model class. Doctrine uses the Data Mapper pattern, whereas Eloquent uses Active Record. Skipping the get() set() methods, a simple class would look like:

use DoctrineORMMapping AS ORM;

use DoctrineCommonCollectionsArrayCollection;

/**

* @ORMEntity

* @ORMTable(name="scientist")

*/

class Scientist

{

/**

* @ORMId

* @ORMGeneratedValue

* @ORMColumn(type="integer")

*/

protected $id;

/**

* @ORMColumn(type="string")

*/

protected $firstname;

/**

* @ORMColumn(type="string")

*/

protected $lastname;

/**

* @ORMOneToMany(targetEntity="Theory", mappedBy="scientist",

cascade={"persist"})

* @var ArrayCollection|Theory[]

*/

protected $theories;

/**

* @param $firstname

* @param $lastname

*/

public function __construct($firstname, $lastname)

{

$this->firstname = $firstname;

$this->lastname = $lastname;

$this->theories = new ArrayCollection;

}

…

public function addTheory(Theory $theory)

{

if(!$this->theories->contains($theory)) {

$theory->setScientist($this);

$this->theories->add($theory);

}

}

This POPO-based model used annotations to define field types that need to be persisted in MongoDB. For example, @ORMColumn(type=”string”) defines a field in MongoDB with the string type firstname and lastname as the attribute names, in the respective lines.

There is a whole set of annotations available here http://doctrine-orm.readthedocs.io/en/latest/reference/annotations- reference.html . If we want to separate the POPO structure from annotations, we can also define them using YAML or XML instead of inlining them with annotations in our POPO model classes.

Inheritance with Doctrine

Modeling one-one and one-many relationships can be done via annotations, YAML, or XML. Using annotations, we can define multiple embedded subdocuments within our document:

/** @Document */

class User

{

// …

/** @EmbedMany(targetDocument="Phonenumber") */

private $phonenumbers = array();

// …

}

/** @EmbeddedDocument */

class Phonenumber

{

// …

}

Here a User document embeds many PhoneNumbers. @EmbedOne() will embed one subdocument to be used for modeling one-one relationships.

Referencing is similar to embedding:

/** @Document */

class User

{

// …

/**

* @ReferenceMany(targetDocument="Account")



*/

private $accounts = array();

// …

}

/** @Document */

class Account

{

// …

}

@ReferenceMany() and @ReferenceOne() are used to model one-many and one-one relationships via referencing into a separate collection.

We saw that the process of connecting data to MongoDB using Python and PHP is quite similar. We can accordingly define relationships as being embedded or referenced, depending on our design decision.

If you found this post useful, check out our book Mastering MongoDB 3.x for more tips and techniques on working with MongoDB efficiently.

Mastering MongoDB 3.x

 


Subscribe to the weekly Packt Hub newsletter. We'll send you the results of our AI Now Survey, featuring data and insights from across the tech landscape.

LEAVE A REPLY

Please enter your comment!
Please enter your name here