This extension is an almost complete, ActiveRecord like support for MongoDB in Yii It originally started as a fork of MongoRecord extension written by tyohan, to fix some major bugs, and add full featured suite for MongoDB developers.
IMPORTANT Info: I've developed this extension as a hobby project. Now I had stopped using Yii in my hobby and work projects. I'm no longer maintaining this code. My codebase is available for easy fork/download on a github. Feel free to continue my work, YMDS already has active community, you can find support mostly on google groups (described bellow).
PLEASE refer to the new FULL-Documentation page
There is also an google groups for topics related to YMDS, everyone are welcome, to post threads, questions, and support requests there.
Work-around for using the OR operator with this extension provided in comments
This is the 1.4 preview release 1
The YMDS feature list has grown up recently, some of new ones are:
OR operator with criteria objectThis is a Preview Release of YMDS 1.4 it is not ready for stable usage I publish it because I need help with testing and code stabilization, anyone are welcome to download, test and submit bug fixes.
EMongoPartialDocument class, that supports full-featured partial loading of documents from DB$set operator/featureIMPORTANT: The version on GitHub is more up to date as fixes are pushed to the project. This may or may not get updated on a regular basis
In your protected/config/main.php config file. Comment out (or delete) the current 'db' array for your database in the components section, and add the following to the file:
'import' => array( ... 'ext.YiiMongoDbSuite.*', ), 'components' => array( ... 'mongodb' => array( 'class' => 'EMongoDB', 'connectionString' => 'mongodb://localhost', 'dbName' => 'myDatabaseName', 'fsyncFlag' => true, 'safeFlag' => true, 'useCursor' => false ), ),
'connectionString' => 'mongodb://username@xxx.xx.xx.xx' where xx.xx.xx.xx is
the ip (or hostname) of your webserver or host.That's all you have to do for setup. You can use it very much like the active record. Example:
$client = new Client(); $client->first_name='something'; $client->save(); $clients = Client::model()->findAll();
Just define following model:
class User extends EMongoDocument { public $login; public $name; public $pass; // This has to be defined in every model, this is same as with standard Yii ActiveRecord public static function model($className=__CLASS__) { return parent::model($className); } // This method is required! public function getCollectionName() { return 'users'; } public function rules() { return array( array('login, pass', 'required'), array('login, pass', 'length', 'max' => 20), array('name', 'length', 'max' => 255), ); } public function attributeLabels() { return array( 'login' => 'User Login', 'name' => 'Full name', 'pass' => 'Password', ); } }
And thats it! Now start using this User model class like standard Yii AR model
NOTE: For performance reasons embedded documents should extend from EMongoEmbeddedDocument instead of EMongoDocument
EMongoEmbeddedDocument is almost identical as EMongoDocument, in fact EMongoDocument extends from EMongoEmbeddedDocument and adds to it DB connection related stuff.
NOTE: Embedded documents should not have a static model() method!
So if you have a User.php model, and an UserAddress.php model which is the embedded document. Lest assume we have following embedded document:
class UserAddress extends EMongoEmbeddedDocument { public $city; public $street; public $house; public $apartment; public $zip; public function rules() { return array( array('city, street, house', 'length', 'max'=>255), array('house, apartment, zip', 'length', 'max'=>10), ); } public function attributeLabels() { return array( 'zip'=>'Postal Code', ); } }
Now we can add this method to our User model from previous section:
class User extends EMongoDocument { ... public function embeddedDocuments() { return array( // property name => embedded document class name 'address'=>'UserAddress' ); } ... }
And using it is as easy as Pie!
$client = new Client; $client->address->city='New York'; $client->save();
it will automatically call validation for model and all embedded documents! You even can nest embedded documents in embedded documents, just define embeddedDocuments() method with array of another embedded documents IMPORTANT: This mechanism uses recurrency, and will not handle with circular nesting, you have to use this feature with care :P
You easily can store arrays in DB!
Simple arrays
Arrays of embedded documents
// add a property for your array of embedded documents public $addresses; // add EmbeddedArraysBehavior public function behaviors() { return array( array( 'class'=>'ext.YiiMongoDbSuite.extra.EEmbeddedArraysBehavior', 'arrayPropertyName'=>'addresses', // name of property 'arrayDocClassName'=>'ClientAddress' // class name of documents in array ), ); }
So for the user, if you want them to be able to save multiple addresses, you can do this:
$c = new Client; $c->addresses[0] = new ClientAddress; $c->addresses[0]->city='NY'; $c->save(); // behavior will handle validation of array too
or
$c = Client::model()->find(); foreach($c->addresses as $addr) { echo $addr->city; }
This is one of the things that makes this extension great. It's very easy to query for the objects you want.
// simple find first. just like normal AR. $object = ModelClass::model()->find()
Now suppose you want to only retrieve users, that have a status of 1 (active). There is an object just for that, making queries easy.
$c = new EMongoCriteria; $c->status('==', 1); $users = ModelClass::model->findAll($c);
and now $users will be an array of all users with the status key in their document set to 1. This is a good way to list only active users. What's that? You only want to show the 10 most recent activated users? Thats easy too.
$c = new EMongoCriteria; $c->active('==', 1)->limit(10); $users = ModelClass::model->findAll($c);
It's that easy. In place of the 'equals' key, you can use any of the following operators
- 'greater' | >
- 'greaterEq' | >=
- 'less' | <
- 'lessEq' | <=
- 'notEq' | !=, <>
- 'in' |
- 'notIn' |
- 'all' |
- 'size' |
- 'exists' |
- 'type' | // BSON type see mongodb docs for this
- 'notExists' |
- 'mod' | %
- 'equals' | ==
- 'where' | // JavaScript operator
*NOTICE: the $or operator in newer versions of mongodb does NOT work with this extension yet. We will add it to the list above when it is fixed.Newer versions of mongo db will work, just not the $or operator. For examples and use for how to use these operators effectively, use the MongoDB Operators Documentation here.
Here are a few more examples for using criteria:
// first you must create a new criteria object $criteria = new EMongoCriteria; // find the single user with the personal_number == 12345 $criteria->personal_number('==', 12345); // OR like this: $criteria->personal_number = 12345; $user = User::model->find($criteria); // find all users in New York. This will search in the embedded document of UserAddress $criteria->address->city('==', 'New York'); // Or $criteria->address->city = 'New York'; $users = User::model()->findAll($criteria); // Ok now try this. Only active users, only show at most 10 users, and sort by first name, descending, and offset by 20 (pagination): // note the sort syntax. it must have an array value and use the => syntax. $criteria->status('==', 1)->limit(10)->sort(array('firstName' => EMongoCriteria::SORT_DESC))->offset(20); $users = User::model()->findAll($criteria); // A more advanced case. All users with a personal_number evenly divisible by 10, sorted by first name ascending, limit 10 users, offset by 25 users (pagination), and remove any address fields from the returned result. $criteria->personal_number('%', array(10, 0)) // modulo => personal_number % 10 == 0 ->sort(array('firstName' => EMongoCriteria::SORT_ASC)) ->limit(10) ->offset(25); $users = User::model()->findAll($criteria); // You can even use the where operator with javascript like so: $criteria->fieldName('where', ' expression in javascript ie: this.field > this.field2'); // but remember that this kind of query is a bit slower than normal finds.
You can use native PHP Mongo driver class MongoRegex, to query:
// Create criteria $criteria = new EMongoCriteria; // Find all records witch have first name starring on a, b and c, case insensitive search $criteria->first_name = new MongoRegex('/[abc].*/i'); $clients = Client::model()->findAll($criteria); // see phpdoc for MongoRegex class for more examples
for reference on how to use query array see: http://www.php.net/manual/en/mongocollection.find.php
// Example criteria $array = array( 'conditions'=>array( // field name => operator definition 'FieldName1'=>array('greaterEq' => 10), // Or 'FieldName1'=>array('>=', 10) 'FieldName2'=>array('in' => array(1, 2, 3)), 'FieldName3'=>array('exists'), ), 'limit'=>10, 'offset'=>25, 'sort'=>array('fieldName1'=>EMongoCriteria::SORT_ASC, 'fieldName4'=>EMongoCriteria::SORT_DESC), ); $criteria = new EMongoCriteria($array); // or $clients = ClientModel::model()->findAll($array);
Total 20 comments
Migration - it just a command, that can access to DB. Use Yii::app()->mongodb to access DB, and some collection like "migrations" to check for command execute status. It's same like migrations.
EMongoDocument has a bug: it does not use _sort criteria when selecting one object using find method. As a result - wrong object selects.
I fix it for me in this way:
Hi!
I'm very interested in using this extension. However, I do use some other extensions that rely on migrations to setup some settings. Is there any plan on supporting some type of dummy migration to satisfy those needs? (when you are changing to a system that used to have migrations for example).
how to compare a string with larger paragraph which is stored in mongoDb?
i want to select the rows which contain the given string in a field which stores a paragraph.Mine is a search features.Please help...
Annotations are great concept, but they require external dependecies and change of Yii users thinking (Yii does not use this anywhere, afaik)
But first, where you want that ideas to put? gitub issues, or here? Anyway, here's my ideas:
Arbitrary type of embedded, embedded array - I already use it in my fork of ymds, just store _class field for each embed
Gather all and each attribute metada in one place, as there are a lot of options like
It would be great to use annotations for this. I developed yii annotation extension, but unfortunatelly it still requires more docs before I publish it. With annotations defining attributes is plain fun, like that:
here is my fork of ymds using annotations and above features: https://github.com/Maslosoft/YiiMongoDbSuite
Hey all,
loong 2 yeas have passed since I finished working with Yii and YMDS.
I'm glad to announce that I'm currently working on full re-write of YMDS.
YMDS2 will not be backward compatible with v1.x versions, as some core concepts where changed:
$orIf you want to help, submit some ideas, pull requests - some core concept code is already on GitHub https://github.com/canni/ymds2
I'll be glad if someone can help with docs(blocks) and proper english speech.
cheers, canni
@vijaykoogu db and mongodb are separate components. If you are using mongo db, and not using mysql, remove db component.
mongodbis not part ofdbconfig. Should be like that:nothing problem with my mongodb drivers, coz i had configured directmongosuit extension and was working fine... it created logs for me in db...
my main.php goes like this...
Your confignuration here is worng:
//mongodb confignuration 'db'=>array( 'mongodb' => array( 'class' => 'EMongoDB', 'connectionString' => 'mongodb://root@127.0.0.1', 'dbName' => 'testdb', 'fsyncFlag' => true, 'safeFlag' => true, 'useCursor' => false ), ),Right one
'mongodb' => array( 'class' => 'EMongoDB', 'connectionString' => 'mongodb://root@127.0.0.1', 'dbName' => 'testdb', 'fsyncFlag' => true, 'safeFlag' => true, 'useCursor' => false ),i have configured the extension as it has been showing on the documentation but still im getting error like this.
my configuration file (main.php) goes like this...
Indeed, this was not optimal. In fact it doesn't work as expected in regards to the Yii AR implementation, which this extension should try to follow.
The branch "release/1.4" has been updated.
Thanks for pointing this out. If you have any more suggestions feel free to open an issue or ask for a pull request.
I'm glad someone finally took the step towards re-unifying all the forks out there (and even more glad someone fixed the typos in the comments ;) )
What disturbs me a bit about several versions out there (including the one in your fork) is the "optimalisation" to the EMongoDocument::model() function. It's really NOT a good idea IMO to create a new instance of the model every time the function is called. This basically destroys any ability to use scopes (as those rely on the "getDbCriteria" linked to the base model instance and it creates a whole bunch of new objects that really aren't needed.
If you would consider reverting this back to the original implementation then this your version would be really useful to me.
Anyway, keep up the good work! :)
Since the extension's main developer has stopped supporting this extension, there has been continued interest, but no real centralized repo for further improvements and bugfixing.
I've forked the original project on GitHub and merged in several outside branches for bugfixes and improvements.
We're currently doing pre-production testing of the extension after these merges, but we may not be using all of its functionnalities. Before releasing a new version, I'd appreciate if some of the users here could take a look.
https://github.com/digitick/yii-mongodb-suite
Checkout the 'release/x.x' or 'develop' branches, as 'master' has not been modified much.
Thank you!
@intel352
thank you for your reply, that is right.
Re: #7485 by @elsonwu
The performance that would occur in your fix is not ideal, as your solution would issue a count and a find for every unique validation, and a find request is already less performant than a count request.
I suggest you instead use the patch I provide here: https://github.com/intel352/YiiMongoDbSuite/commit/65f7ae77c9b4364ba22a94c322555b33b6a16222
When I update a record, such as user and I set the field email unique. I update the username and the email not modified, then it will show error. Here is my bugfix for it.
https://github.com/mintao/YiiMongoDbSuite
anyone forked this extension ?
Can this work together with CActiveDataProvider? -> Yes it does for sure; I am using MongoDB with MySQL.
Is this question make sense? -> Not really since you are using Yii where compatibility and interoperability matters.
Leave a comment
Please login to leave your comment.