2012-09-05 114 views
6

我有一個嵌入文檔的文檔。當我第一次創建一個對象時,一切正常,但是當我嘗試更新文檔時,嵌入的文檔不會被更新。如何在Doctrine MongoDB中更新嵌入式文檔?

/** @MongoDB\Document */ 
class DocumentA 
{ 
    /** @MongoDB\EmbedOne(targetDocument="DocumentB") **/ 
    protected $docB; 

    /** @MongoDB\String */ 
    protected $valueA; 
} 

/** @MongoDB\EmbeddedDocument */ 
class DocumentB 
{ 
    /** @MongoDB\String */ 
    protected $valueB; 
} 

在我的應用程序中,我查詢文檔,更新值並將它們保存到數據存儲區。

// Variant A – Does not work 
$document = ... // find from data store 
$document->setValueA('Hello World'); 
$document->getDocB()->setValueB('foo baz'); 

$om->persist($document); 
$om->flush(); 

如果我不更新嵌入的文件,但設置一個新的,一切工作正常:

// Variant B - Does work 
$document = ... // find from data store 
$document->setValueB('Hello World 2'); 
$document->setDocB(new DocumentB()); 
$document->getDocB()->setValueB('foo baz 2'); 

$om->persist($document); 
$om->flush(); 

正如我所說的,方案B工作正常。但是,在我的應用程序中,文檔更加複雜,每次需要更新時,爲嵌入式文檔創建新對象都是不切實際的。有沒有一種方法可以告訴Doctrine ODM查看嵌入式文檔的值以決定是否應該更新?

回答

0

MongoDB只有原子操作。 您有以下選項: 1.查詢文檔,找到合適的子文檔,更新整個文檔或其部分。 優點:易邏輯 缺點:非原子 2.使用位置$操作符是您的子文檔在列表中。

2

我面臨完全相同的問題。事實證明,UnitOfWork似乎無法計算嵌入其他文檔的文檔的變更集,儘管我一直無法弄清楚爲什麼...因此,當我比較實際值和原始值時,單元的工作對兩者都表現出相同的價值。與方案A來講,當你

$document->getDocB()->setValueB('foo baz'); 

工作的單位顯示爲「foo巴茲」兩個舊的和新的價值,並且不會將其識別爲一個變化,爲此將不會更新。

無論如何,這利茲解決方法:

$document = ... // find from data store 
$document->setValueA('Hello World'); 
$docB = $document->getDocB(); 
$docB->setValueB('foo baz'); 
$om->detach($docB); 
$om->persist($document); 
$om->flush(); 

這使得工作單元識別docB $文件作爲新設置的文件,將刷新它的預期。

+0

我有問題,用不同的嵌入式文檔替換。在我的情況DocumentB不是一個EmbeddedDocument,而是一個文檔。在這裏顯示的對象上使用detach也可以在這種情況下工作。 – Onema