2013-07-20 39 views
4

我需要在iiimongodbsuite中執行upsert命令。 我試過在iiimongodbsuite中嵌入文檔Upsert

$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); 

但是這顯示一個錯誤。

Murls模型定義如下

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 
       ), 
     ); 
     } 

    } 

和模型Medithtml作爲

class Medithtml extends EMongoEmbeddedDocument{ 
    public $html; 
    public $path; 
    public $ci; 

    public static function model($className=__CLASS__) 
    { 
     return parent::model($className); 
    } 


} 

我需要實現的是與$title記錄可以有$html$path$ci n個。 任何幫助將不勝感激。 我尋找是存儲這樣的

 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', 
    ), 
), 
) 

只有意見陣列將被更新的數據,如果用的'title'的特定組合和'userid' exists.If它不存在沒有一個新的記錄將被插入

記錄
+1

我不認爲這種複雜的UPSERT可以通過活動記錄來完成,我想你可能需要通過實際觸摸數據庫來完成。 YiiMongoDBSuite不知道子文檔被插入並試圖使其可能會導致次優編碼 – Sammaye

+0

@Sammaye謝謝 – user7282

回答

1

最後我得到了這樣的解決方案:

 $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); 
     } 
3

您從錯誤的類繼承。要保存文檔,您必須從EMongoDocument繼承而不是EMongoEmbeddedDocument。這些類是相似的,但具有不同的目的。

  • EMongoEmbeddedDocument僅用於嵌入文檔,它應該只對嵌入式文件
  • EMongoDocumentEMongoEmbeddedDocument延伸與方法實際數據保存到數據庫中。

有關意見陣列,你有兩個選擇:

  1. 使用純PHP陣列 - 簡單的少maintanable,功率更低,erron容易..
  2. 使用array of embedded documents - 每個評論的文檔,所以可以被驗證,具有剛性結構等

默認save/insert/update存儲所有屬性。對於部分更新,使用$attributes的組合並將$modify設置爲true。 警告:傳遞不帶$modify的屬性數組將只存儲傳遞的屬性,丟棄文檔的其餘部分。

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

所以你的情況,你可以更新這樣的:

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

或者它是否可以爲你ovverride整個文件只保存:

$model->save(); 

注:複合pk ovverride primaryKey()

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

嗯,那好計算器有草稿自動保存功能:)

+0

我認爲你還沒有完全理解我的問題。我改寫了我的問題 – user7282

+0

注意點2關於嵌入。我的意思是嵌入式文件(不是嵌入式數組)的陣列。但是,默認的yii mongodb套件分支本身不支持它。我更新了有關嵌入文檔數組文檔鏈接的答案。嵌入式文檔數組將存儲您需要的結構,並允許Yii使用OO訪問。作爲問題的第二部分,複合主鍵和部分更新應該沒問題。 – 2013-07-23 08:36:32