I need to perform an 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 this shows an error.
Murls 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 model Medithtml as
class Medithtml extends EMongoEmbeddedDocument{
public $html;
public $path;
public $ci;
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}
What I need to achieve is that a record with $title
can have n number of $html
, $path
and $ci
.
Any help will be appreciated.
What I am looking is 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 record with a particular combination of 'title'
and 'userid'
exists.If it doesn not exists a new record will be inserted
You are inheriting from wrong class. To save document you must inherit from EMongoDocument
not EMongoEmbeddedDocument
. These classes are similar but have different purpose.
EMongoEmbeddedDocument
Is for embedded documents only, it should be used only for embedded documentsEMongoDocument
extends fromEMongoEmbeddedDocument
with methods to actually save data to db.
For array of comments, you have two options:
- Use plain php array - simple less maintanable, less power, erron prone..
- Use array of embedded documents - each comment is document, so can be validated, has rigid structure etc.
By default save
/insert
/update
stores all attributes. For partial updates use combination of $attributes
and set $modify
to true. Warning: Passing array of attributes without $modify
will store only passed attributes, discarding rest of 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 that:
$model->update(array('comments'), true);
Or if it's ok for you to ovverride whole document just save:
$model->save();
Note: for composite pk ovverride primaryKey()
:
public function primaryKey()
{
return array('title', 'userid');
}
Uh, good that stackoverflow have drafts autosave feature:)
Finally I got solution in 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);
}
来源:https://stackoverflow.com/questions/17760038/upsert-embedded-document-in-yiimongodbsuite