Wie kann Doctrine ODM verwendet werden, um eine Eins-zu-Eins-bidirektionale Referenz zu erstellen, die bei Verwendung eines anderen Feldes als des Primärschlüssels für die Referenz "Lazy Loads" verwendet?Doctrine ODM OneToOne bidirektionale Referenz mit repositoryMethod
Ich habe zwei Sammlungen in MongoDB mit Dokumenten, Artikel und ArticleMetaData. Für jedes Artikeldokument gibt es eine ArticleMetaData und umgekehrt. (Eine bidirektionale OneToOne-Beziehung.) Aus beiden Gründen müssen die beiden Dokumenttypen in separaten Sammlungen sein. Beide Sammlungen werden von externen Systemen aktualisiert, die keine Kenntnis über die Mongo-IDs haben. Sie enthalten jedoch ein gemeinsames Feld "groupcode", mit dem der richtige Artikel mit seinen Metadaten abgeglichen werden kann.
Ich versuche Doctrine so zu konfigurieren, dass ich die Metadaten für ein Artikelobjekt und einen Artikel aus seinem Metadatenobjekt bekommen kann, aber ich möchte sie faul geladen halten. (Es besteht keine Notwendigkeit für das andere Ende abzufragen, wenn ich es nicht brauchen.)
die Zuordnungen wie folgt aussehen:
Foo\BarBundle\Document\Article:
repositoryClass: Foo\BarBundle\Repository\ArticleRepository
changeTrackingPolicy: DEFERRED_EXPLICIT
collection: article
type: document
fields:
id:
id: true
groupcode:
type: int
index: true
unique:
order: asc
...
referenceOne:
metaData:
targetDocument: Foo\BarBundle\Document\ArticleMetaData
mappedBy: groupcode
repositoryMethod: findOneByArticle
Foo\BarBundle\Document\ArticleMetaData:
repositoryClass: Foo\BarBundle\Repository\ArticleMetaDataRepository
changeTrackingPolicy: DEFERRED_EXPLICIT
collection: article_meta
fields:
id:
id: true
groupcode:
type: int
index: true
unique:
order: asc
...
referenceOne:
article:
targetDocument: Foo\BarBundle\Document\Article
mappedBy: groupcode
repositoryMethod: findOneByMetaData
Und die Repository-Methoden oben erwähnt:
// In the ArticleRepository
public function findOneByMetaData(ArticleMetaData $metadata)
{
$article = $this
->createQueryBuilder()
->field('groupcode')->equals($metadata->getGroupcode())
->getQuery()
->getSingleResult();
$article->setMetaData($metadata);
return $article;
}
// In the ArticleMetaDataRepository
public function findOneByArticle(Article $article)
{
$metaData = $this
->createQueryBuilder()
->field('groupcode')->equals($article->getGroupcode())
->getQuery()
->getSingleResult();
$metaData->setArticle($article);
return $metaData;
}
Es scheint alles ganz gut zu funktionieren. Ich kann einen Artikel oder ArticleMetaData abfragen und bekomme die andere Seite, nur Das Problem ist: es scheint nicht zu faul laden. Wenn ich für einen Artikel abfragen:
$article = $documentManager
->getRepository('FooBarBundle:Article')
->findOneBy(['groupcode' => 123]);
Viele Abfragen ausgeführt werden:
doctrine.INFO: MongoDB query: {"find":true,"query":{"groupcode":123},"fields":[],"db":"development","collection":"article"}
doctrine.INFO: MongoDB query: {"limit":true,"limitNum":1,"query":{"groupcode":123},"fields":[]}
doctrine.INFO: MongoDB query: {"limit":true,"limitNum":null,"query":{"groupcode":123},"fields":[]}
doctrine.INFO: MongoDB query: {"find":true,"query":{"groupcode":123},"fields":[],"db":"development","collection":"article_meta"}
doctrine.INFO: MongoDB query: {"limit":true,"limitNum":1,"query":{"groupcode":123},"fields":[]}
doctrine.INFO: MongoDB query: {"find":true,"query":{"groupcode":123},"fields":[],"db":"development","collection":"article"}
doctrine.INFO: MongoDB query: {"limit":true,"limitNum":1,"query":{"groupcode":123},"fields":[]}
Was mache ich falsch? Gibt es eine Art und Weise, wie ich eine bidirektionale Referenz mit verzögerter Ladeoperation erreichen kann, die die obigen Einschränkungen aufweist?
Edit:
Nach der Lektüre Rob Holmes' Antwort nahm ich einen Test in den Repository-Methoden, die das Problem verursacht haben könnten. Leider bleibt das Problem bestehen und es werden immer noch 3 Abfragen ausgeführt, wobei eine (oder höchstens zwei) ausreicht.
Vielen Dank für Ihren Vorschlag. Ich glaube, Sie haben Recht, dass ein solcher Anruf falsch ist. In der Praxis macht das leider keinen Unterschied. Ich habe meinen Beitrag jedoch mit Ihren Verbesserungen aktualisiert. – Xatoo