[EXTENSION] directmongosuite

Please add comments here and not at the extension page: directmongosuite

i am interested to this extension :lol: ; why don’t you put it on google code or github or bitbucket ,

before download it i always to read the source code first . :D

Why don’t you download it from the extension page?

There is the directmongosuite.0.1.zip ready for download (only 22KB).

You don’t have to install it if you don’t want.

I get an error when I try to use the Clear Log function in the Log Viewer:

‘CException’ with message 'Property “EDMSLogViewer.db” is not

defined.’ on line 254 of EDMSLogViewer.php.

Looks like you just need to re-implement the creation of the capped collection using your new DB connections.

Thanks for the hint. Yes I forgot to implement the new DB connection on migrating.

Fixed and extension updated.

@joblo :

in EDMSQuery class this function has wrong result:




	public function findArray($criteria=array(),$select=array(),$sort=array(),$limit=null)

	{

	   	$result = array();


		$cursor = $this->findCursor($criteria,$select,$sort,$limit);


		if (!empty($cursor) && $cursor->count())

			foreach ($cursor as $id => $value)

			   $result[] = array();


		return $result;

	}



$result[] = array(); //you must do something wrong here :rolleyes:

may be it should be : $result[] = $value;

Thanks yiqing95. Fixed and published as v0.1.2.

Added findCountBy and some minor changes.

@joblo:

this function in EDMSQuery should be modified to :




 public static function modelToArray($model)

    {

        if (method_exists($model, 'getAttributes'))

            return $model->getAttributes(); //set model attributes with no validation

        else

        { //assign the values to the public properties

            $class = new ReflectionClass(get_class($model));

            $attributes = array();

            foreach ($class->getProperties() as $property)

            {

                if ($property->isPublic() && !$property->isStatic()) {

                    $key = $property->getName();

                    $attributes[$key] = $model->$key;

                }

            }


            return $attributes;

        }

    }



now your 's :




   ...

   $class=new ReflectionClass(get_class($model));

			$attributes = array();

			foreach($model->getProperties() as $property)

			{

				if($property->isPublic() && !$property->isStatic())

				{

				  $key=$property->getName();

				  $attributes[$key] = $model->$key;

				}

			}



change the $model->getProperties =====> $class->getProperties :P

I have detected this bug when working on the update 0.1.2.

Please take a look at this latest version.

The function EDMSQuery::arrayToModel and EDMSDataProvider::fetchData has been changed there for a better performance.

If using non CModel classes the model properties should not be analyzed (new ReflectionClass) for each row on fetching data.

:rolleyes: i v download the latest version . seems everything is ok now .

        well done joblo , great extension !

Hi,

great extension.

I’d like to ask you for assistance in setting authmanager.

I’ve looked through the source of EDMSAuthManager, and I am not able to understand where the authorization rules are saved to.

I have the following set up in my config/main.php:


 

//uses the collection 'edms_authmanager' for the authmanager

        'authManager' => array(

            'class' => 'EDMSAuthManager',

            'connectionId' => 'mongodb'

        ),



Yet, when I save my authorization rules, I do not see the collection in my mongodb nor the file in protected/data/auth.php

Is there something I should check first, can someone post their successful configuration if they moved to mongodb for their auth rules?

Thanks!

I believe I got it to work.

It wasn’t showing anything in my collections because I forgot to add “Save” to my authorization rules. That was the only difference between PhpAuth and the DbAuth way of doing things.

Again, awesome extension!

Nice extension!

Have been using directmongosuite with yiimongodbsuite and both tend to work well together without any problem so far.

Thank you, for that nice extension.

I have tow questions:

1.) how to set slaveOkay=true? -> http://www.php.net/manual/de/mongo.setslaveokay.php

Or is it on by default?

2.) how to realize updates with multiple operators, like:


{ $set : { x : 1 }, $inc : { y : 1 } }

Is there something like an wiki, where I can write down my examples? Maybe other users (which starts with mongoDB) has the same questions?!

Thank you.

To answer my own question Nr. 2:

I decided change the atomicUpdate method in order to have to possibility to process different modifier at one mongo request:


	public function atomicUpdate($criteria,$values,$modifier = '$set', $multiple = false,$options=array())

	{

		if (empty($values) and !is_array($modifier))

			return false;

		

		if(is_array($modifier))  {$action=$modifier;}

		  else {$action = array($modifier => $values);}

	

		

		if ($multiple)

		   $options = array_merge($options, array('multiple'=>true));


		return $this->getCollection()->update($criteria,$action,$options);

	}

That means, you can leave $values empty and use $modifier as an array with the following layout:




	  array($modifier1 => array($field1=>$value1,

	 			    $field2=>$value2),

	 	$modifier2=> array($field3=>$value5,));

Could that be an valid solution?

Sorry for the delay, I didn’t get a message that there is a new item in this topic.

1.) SlaveOK is true by default, but in the next release (coming soon) there will be a solution for that too.

2.) Thanks for the input, I will change the code like this

Hi,

right now we are using directmongosuite and yiimongodbsuite side by side, which works well on an MongoDB replication set.

directmongosuite is using the connection settings from the yiimongodbsuite:


	'behaviors' => array(

   	'edms' => array(

      	'class'=>'EDMSBehavior',

      	'connectionId' => 'mongodb',

 			'debug'=>true //for extended logging

       )

    ),


[....]

        /*yiimongodbsuite zeugs*/

        'mongodb' => array(

        	'class'            => 'EMongoDB',

        	'connectionString' => 'mongodb://server1,server2',

        	'replicaSet'       => 'replSet_RS',

        	'dbName'           => 'testdb',

        	'fsyncFlag'        => true,

        	'safeFlag'         => true,

        	'useCursor'        => false

        ),

	   

Some hours before we did some changes on the Primary/Secondary configuration for the MongoDB.

All the application components, which are using yiimongodbsuite working without any errors with this new configuration.

All the application components using directmongosuite gets the following error:

at this point:


305     public function findOne($criteria,$select=array())

306     {

307         //always add the '_id'

308         if (!empty($select) && !in_array('_id',$select))

309             array_push($select,'_id');

310 

311         $cursor = $this->getCollection()->findOne($criteria, $select);   <---here

312 

313         return !empty($cursor) ? $cursor : false;

314     }

May you have any idea what is goning on here?

Thank you, rall0r.

I don’t know anything about your configuration.

If you google for ‘mongodb slaveok php’ you will find a lot of information about this.

It seems you try to read from a secondary without setSlaveOk = true.

See the mongodb manual and the php manual.

You have to configure the options of the edms-component with ‘replicaSet’=>…

Maybe you have to add ->setSlaveOkay in the code of the ‘function edmsMongoDb’ of the file EDMSBehavior.

In the next release (coming soon) if have added a property ‘setSlaveOkay’ so that you can configure this call in the config/main.php.

But how did you configure the yiimongodbsuite with replicaSet=…?

As I can see in the source, the replicaSet-option is not available in EMongoDb.php from yiimongodbsuite.

Where is setSlaveOkay is set in the yiimongodbsuite?

I can’t find this in the source.

Please compare the codes from EMongoDb.php and EDMSConnection.php and how ‘new Mongo’ is called.

Hi Joblo,

right. But the point is: not to read from slave, becaus by using replicaSets, the PHP-mongoDB driver has to choose the master/primary. (i think so)

ups… i forget, that I modified the getConnection() method from yiimongodbsuite. Probably this is the point, why yiimongodbsuite works and directmongosuite doesn’t.

My new getConnetion method from yiimongodbsuite looks like that:


	public function getConnection()

	{

		if($this->_mongoConnection === null)

		{

			try

			{

				Yii::trace('Opening MongoDB connection', 'ext.MongoDb.EMongoDB');

				if(empty($this->connectionString))

					throw new EMongoException(Yii::t('yii', 'EMongoDB.connectionString cannot be empty.'));


				if($this->persistentConnection !== false)

					$this->_mongoConnection = new Mongo($this->connectionString, array(

						'connect'=>$this->autoConnect,

						'persist'=>$this->persistentConnection,

						'replicaSet'=>$this->replicaSet          <--- added this

					));

				else

					$this->_mongoConnection = new Mongo($this->connectionString, array(

						'connect'=>$this->autoConnect,

						'replicaSet'=>$this->replicaSet         <--- added this

					));


				return $this->_mongoConnection;

			}

			catch(MongoConnectionException $e)

			{

				throw new EMongoException(Yii::t(

					'yii',

					'EMongoDB failed to open connection: {error}',

					array('{error}'=>$e->getMessage())

				), $e->getCode());

			}

		}

		else

			return $this->_mongoConnection;

	}



So i thought this configuration…




        'behaviors' => array(

        'edms' => array(

        'class'=>'EDMSBehavior',

        'connectionId' => 'mongodb',

                        'debug'=>true //for extended logging

       )

    ),



…will work with replicaSets too, because yiimogodbsuite does - which is wrong, because directmongosuite "only" takes the connection-information, but not the connection method (logisch :-/ )

So I have to add 2 things at directmongosuite :

1.) slaveOk=true <- in order to read from slave if the slave is "closer" than the master and

2.) replicaSet configuration to the code from directmongosuite

…right?!?

In directmongosuite you can config the replicaSet in main.php by using the options of the EDMSConnection component.

The options array is used when calling ‘new Mongo(…)’.





 'components'=>array(

 

        //configure the mongodb connection

        //set the values for server and options analog to the constructor 

        //Mongo::__construct from the PHP manual

        'edms' => array(

            'class'            => 'EDMSConnection',

            'dbName'           => 'testdb',

            'options'  => array('replicaSet'=>....); 

        ),




setSlaveOk is supported in the next release, so you have to change the EDMSBehavior.php to something like below.

Then you can configure the behavior to setSlaveOkay=true in config/main.php

This is a preview of v2.5 …




   

class EDMSBehavior extends CBehavior

{

    /**

     * The connection id for config in config/main

     * @var string

     */

	public $connectionId = 'edms';

    /**

     * Set Mongo::setSlaveOkay after creating Mongo if set

     * @var boolean

     */

	public $setSlaveOkay = null;  //<---------------- add this property   

   


/**

	 * Get edmsMongoDb instance

	 * @since v1.0

	 */

	public function edmsMongoDb($dbName=null,$connectionId = null)

	{

		if (empty($dbName))

			$dbName = $this->edmsGetDbName($connectionId);


		if (empty($connectionId))

			$connectionId = $this->edmsGetConnectionId();


		if (!isset(self::$_db))

			self::$_db = array();


		if (!isset(self::$_db[$connectionId][$dbName]))

		{

			if ($this->edmsIsDebugMode())

			   self::edmsLog("Selecting db: $connectionId.$dbName","edms.debug.db.$dbName.$connectionId");


			$mongo = $this->edmsMongo($connectionId);


            if(isset($this->setSlaveOkay))

                $mongo->setSlaveOkay($this->setSlaveOkay);


            self::$_db[$connectionId][$dbName] =  $mongo->selectDB($dbName);

		}


		return self::$_db[$connectionId][$dbName];

	}