Showing posts with label MongoDB. Show all posts
Showing posts with label MongoDB. Show all posts

Nov 26, 2010

Basic inverted index in MongoDB

i m attracted by Ward Bekker's article Simple ranked text search for MongoDB and his ruby code, he used mapreduce to create inverted index for a set of documents, and ranked the search result by another mapreduce. i modified a bit his code and implement in my PHP application.

Oct 31, 2010

Basic usage of MapReduce in MongoDB

After reading some useful MongoDB MapReduce materials (see References below), it is time to try it myself in practice. Consider a business rating system, it allows users to rate businesses by selecting the point in the range 1(bad)-5(good), the document structure is as follow. The business 'Old Novice' got 2 ratings.
{
  name: 'Old Novice',
  rating : [ {user: 'ngsiolei', point: 3},
             {user: 'lei', point: 4} ]
}

Oct 28, 2010

Creating MongoDB connection in Zend Framework

As of this writing, MongoDB is not yet supported by Zend Framework's latest release, 1.10.8. For learning purpose, i try to use MongoDB with ZF.

To initial a MongoDB connection in Zend_Application, a custom resource plugin is needed. After studying Matthew Weier O'Phinney's post and existing resource plugins, i create a basic one as follow. In this case, i only focus on single host connection. init() reads the parameters and returns a MongoCollection object.

<?php

// library/My/Application/Resource/Mongo.php

class My_Application_Resource_Mongo extends
      Zend_Application_Resource_ResourceAbstract {

    protected $_params = array();

    public function setParams(array $params) {
        $this->_params = $params;
        return $this;
    }   

    public function init() {
        $dns = 'mongodb://';  
        if (isset($this->_params['dbname'])) {
            if (isset($this->_params['username']) &&  
                isset($this->_params['password'])) {
                $dns .= $this->_params['username'] . 
                        ':' . $this->_params['password'] . '@';
            }   
            if (isset($this->_params['hostname'])) {
                $dns .= $this->_params['hostname'];
            }   

            if (isset($this->_params['port'])) {
                $dns .= ':' . $this->_params['port'];
            }   
        } else {
            throw new Exception(__CLASS__ . ' is missing parameters.');
        }   
        try {
            $connection = new Mongo($dns);
            return $connection->selectDB($this->_params['dbname']);
        } catch (MongoConnectionException $e) {
            throw new Exception($e->getMessage());
        }   
    }   
}

In configuration file, define autoloadernamespaces and pluginPaths so that bootstrap class can find the custom resource plugin.
; application/configs/application.ini
[production]
;...
autoloadernamespaces[] = "My_"
pluginPaths.My_Application_Resource = "My/Application/Resource"
resources.mongo.params.hostname = "localhost"
resources.mongo.params.dbname = "test"
;...

i feel comfortable to directly work with MongoCursor object, its methods insert(), find(), update(),... are exactly what i want, so i simply call them in the Mapper without introducing an Application_Model_User class to handle User object, as in quick start example.

<?php

// application/models/UserMapper.php

class Application_Model_UserMapper {

    private $_db;
    private $_name = 'user';
    private $_collection;

    public function __construct() {
        $frontController = Zend_Controller_Front::getInstance();
        $this->_db = $frontController->getParam('bootstrap')
                                     ->getResource('mongo');
        $this->_collection = $this->_db->selectCollection($this->_name);
    }

    public function insert($doc, $options = array()) {
        return $this->_collection->insert($doc, $options);
    }

    public function find($query = array(), $fields = array()) {
        return $this->_collection->find($query, $fields);
    }

    public function findOne($query = array(), $fields = array()) {
        return $this->_collection->findOne($query, $fields);
    }

    public function update($criteria, $newObj, $options = array()) {
        return $this->_collection->update($criteria, $newObj, $options);
    }
//...
}

In controller, i can simply instantiate UserMapper object, and treat it as MongoCursor.

<?php

// application/controllers/IndexController.php

class IndexController extends Zend_Controller_Action {

    public function indexAction() {
        $userMapper = new Application_Model_UserMapper();
        $cursor = $userMapper->find();
        //...
    }
}