W jaki sposób Doctrine ODM może być użyty do utworzenia dwukierunkowego odniesienia typu "jeden do jednego", który leniwy ładuje się przy użyciu pola innego niż klucz podstawowy dla odniesienia?Doctrine ODM OneToOne Bi-Directional Reference using repositoryMethod
Mam dwie kolekcje w MongoDB z dokumentami, artykułem i artykułemMetaData. Dla każdego dokumentu artykułu istnieje artykułMetaData i vice versa. (Dwukierunkowa relacja OneToOne). Ze względu na starsze wersje dwa typy dokumentów muszą znajdować się w osobnych kolekcjach. Obie kolekcje są aktualizowane przez systemy zewnętrzne, które nie mają wiedzy na temat identyfikatorów Mongo. Zawierają jednak wspólne pole "groupcode", które można wykorzystać do dopasowania właściwego artykułu do jego metadanych.
Próbuję skonfigurować Doctrine w taki sposób, aby uzyskać metadane dla obiektu artykułu i artykułu z jego obiektu meta-danych, ale chcę je zachować leniwy załadowany. (Nie ma potrzeby, aby zapytać o drugim końcu, kiedy nie jest to potrzebne).
mapowania wyglądać następująco:
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
i metod repozytorium wspomniano powyżej:
// 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;
}
Wszystko wydaje się działać całkiem dobrze. Mogę zapytać o artykuł lub artykułMetaData i dostać drugą stronę, tylko problemem jest: nie wydaje się leniwy załadować. Kiedy zapytać o artykuł:
$article = $documentManager
->getRepository('FooBarBundle:Article')
->findOneBy(['groupcode' => 123]);
Wiele zapytań są wykonywane:
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":[]}
Co robię źle? Czy istnieje sposób, w jaki mogę osiągnąć leniwy ładowanie dwukierunkowego odniesienia jeden do jednego z powyższymi ograniczeniami?
Edit:
Po przeczytaniu odpowiedź Roba Holmesa usunąłem test w repozytorium metod, które mogą być przyczyną problemu. Niestety, problem nadal istnieje i wciąż są wykonywane 3 kwerendy, w których jedna (lub co najwyżej dwie) wystarcza.
Dziękuję za sugestię. Uważam, że masz rację, że takie wezwanie jest złe. Niestety w praktyce nie robi to żadnej różnicy. Mimo to zaktualizowałem swój post, wprowadzając usprawnienia. – Xatoo