Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Caching MongoDB objects in PHP

I've been trying to write "good code" and use dependency injection to pass database objects in the constructors of my classes.

Constructors are generally taking this form:

public function __construct(MongoDB $db) {
    $this->collection = $db->collectionName;
}

I've noticed that for each object created, a new MongoCollection is created. (i.e. accessing the $db->collectionName property twice returns two distinct objects, not the same object)

I've been using an ActiveRecord style base class, so that objects are able to CRUD themselves.

Now when I use some sort of getAllRecords() function, and return 100s of these objects, 100s of MongoCollection objects are created. (A quick look at the driver source seems to indicate new objects are created there too, not just new representations in PHP)

I've gotten around this by wrapping both Mongo and MongoDB classes to implement caching.

class MyMongo extends Mongo
{
    private $objectCache = array();

    public function __get($name) {
        return array_key_exists($name, $this->objectCache)
            ? $this->objectCache[$name]
            : $this->objectCache[$name] = new MyMongoDB($this, $name);
    }
}

class MyMongoDB extends MongoDB
{
    private $objectCache = array();

    public function __get($name) {
        return array_key_exists($name, $this->objectCache)
            ? $this->objectCache[$name]
            : $this->objectCache[$name] = new MongoCollection($this, $name);
    }
}

My questions are as follows:

  • Is this intended behaviour of MongoDB? Should it really be returning a new object each time, or is it a bug/feature in the PHP driver or Mongo itself (is there a use-case for needing 2 objects for the same collection?)
  • Will I cause problems for myself by caching either/both MongoDB and MongoCollection objects that are created, and re-using them.
  • How do other people typically handle working with MongoDB? Should I be using a different approach entirely? (I.e. DataMapper)

Thanks,

Leigh.

like image 901
Leigh Avatar asked Mar 29 '12 14:03

Leigh


2 Answers

It's intentional, as collections have properties other than their names associated with them (w and wtimeout at the moment, more planned for the future). If all you care about are the names, then it's fine to cache them.

like image 132
kristina Avatar answered Nov 15 '22 04:11

kristina


I've been passing the MongoCollection into my objects instead of the MongoDb. My reasoning was that choosing the collection in the object would be a hidden dependency (may be overkill) and then in my unit tests, I can mock the MongoCollection object.

like image 26
H Hatfield Avatar answered Nov 15 '22 05:11

H Hatfield