Consolidate an embedded document in yiimongodbsuite

I need to run the upsert command in yiimongodbsuite. I tried

$model = new Murls(); $model->userid=$userid; $model->title=$title; $model->edits[0] = new Medithtml(); $model->edits[0]->path= $htm; $model->edits[0]->html=$path; $model->edits[0]->ci=$ci; $model->update(array('_id'=>$rec->_id ),array('userid', 'title','edits' ), true ); 

But it shows an error.

The Merles model is defined as follows

  class Murls extends EMongoDocument { public $userid; public $title; public $edits; public static function model($className=__CLASS__) { return parent::model($className); } // This method is required! public function getCollectionName() { return 'murls'; } public function attributeLabels() { return array( 'html'=>'Html', ); } public function embeddedDocuments() { return array( // property name => embedded document class name 'edits'=>'Medithtml', ); } public function behaviors(){ return array( 'embeddedArrays' => array( 'class' => 'ext.YiiMongoDbSuite.extra.EEmbeddedArraysBehavior', 'arrayPropertyName' => 'edits', // name of property, that will be used as an array 'arrayDocClassName' => 'Medithtml' // class name of embedded documents in array ), ); } } 

and the Medithtml model as

 class Medithtml extends EMongoEmbeddedDocument{ public $html; public $path; public $ci; public static function model($className=__CLASS__) { return parent::model($className); } } 

What I need is that an entry with $title can have n numbers $html , $path and $ci . Any help would be appreciated. I am looking to store data like this

  array ( '_id' => MongoId::__set_state(array( '$id' => '51ee1956d39c2c7e078d80da', )), 'userid' => '12', 'title' => 'Mongo', 'edits' => array ( 0 => array ( 'html' => 'html>body>div:nth-child(2)>a>div>a>div', 'path' => 'ssssss', 'ci' => '1', ), 1 => array ( 'html' => 'html>body>div:nth-child(2)>a>div:nth-child(3)>a>h2', 'path' => '/assets/img/demo/demo-avatar9604.jpg', 'ci' => '2', ), 2 => array ( 'html' => ' html>body>div:nth-child(2)>a>div:nth-child(3)>a>center:nth-child(16)>a>h1', 'path' => '333', 'ci' => '3', ), ), ) 

Only the comments array will be updated if there is an entry with a specific combination of 'title' and 'userid' . If it does not exist, a new entry will be added.

+4
source share
2 answers

Finally, I got the solution this way:

  $rec = $model->find($criteria) ; if($rec){ foreach($rec->edits as $editarray){ $var[]=$editarray; } $edits_new= new Medithtml(); $edits_new['html']=$htm; $edits_new['ci']=$ci; $edits_new['path']=$path; $var[]=$edits_new; $rec->edits=$var; $rec->userid=$userid; $rec->title=$title; $rec->update(array('edits' ), true); } 
+1
source

Inherited from the wrong class. To save a document, you must inherit from EMongoDocument not EMongoEmbeddedDocument . These classes are similar, but have a different purpose.

  • EMongoEmbeddedDocument Used only for embedded documents, it should be used only for embedded documents
  • EMongoDocument distributed from EMongoEmbeddedDocument with methods for actually storing data on db.

For an array of comments, you have two options:

  • Use a simple php array - simple, less manageable, less power, erron prone ..
  • Use an array of embedded documents - each comment is a document, so you can check it, have a rigid structure, etc.

By default, save / insert / update stores all attributes. For a partial upgrade, use the $attributes combination and set the $modify parameter to true. Warning Passing an attribute array without $modify will only store past attributes, discarding the rest of the document.

 public function save($runValidation = true, $attributes = null) ... public function insert(array $attributes = null) ... public function update(array $attributes = null, $modify = false) ... 

So, in your case, you can update like this:

 $model->update(array('comments'), true); 

Or, if you just have to override the entire document, just save:

 $model->save(); 

Note: for composite pk ovverride primaryKey() :

 public function primaryKey() { return array('title', 'userid'); } 

Good thing stackoverflow has an end-to-end autosave function :)

+3
source

Source: https://habr.com/ru/post/1492441/


All Articles