gpt4 book ai didi

php - Doctrine ODM OneToOne Bi-Directional Reference using repositoryMethod

转载 作者:IT老高 更新时间:2023-10-28 13:16:42 25 4
gpt4 key购买 nike

如何使用 Doctrine ODM 来创建延迟加载的一对一双向引用,同时使用主键以外的字段作为引用?

我在 MongoDB 中有两个包含文档的集合,Article 和 ArticleMetaData。对于每个 Article 文档,都有一个 ArticleMetaData,反之亦然。 (OneToOne 双向关系。)出于遗留原因,这两种文档类型需要位于不同的集合中。这两个集合都由不了解 Mongo ID 的外部系统更新。然而,它们确实包含一个共享字段“groupcode”,可用于将正确的文章与其元数据匹配。

我尝试以这样一种方式配置 Doctrine,即我可以从其元数据对象中获取文章对象和文章的元数据,但我想让它们保持延迟加载。 (不需要的时候就不用查询另一端了。)

映射如下:

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

以及上面提到的存储库方法:

// 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;
}

这一切似乎都运作良好。我可以查询 Article 或 ArticleMetaData 并获取对方,只是问题是:它似乎没有延迟加载。当我查询文章时:

$article = $documentManager
->getRepository('FooBarBundle:Article')
->findOneBy(['groupcode' => 123]);

执行了很多查询:

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":[]}

我做错了什么?有没有办法可以完成具有上述约束的延迟加载一对一双向引用?

编辑:

阅读 Rob Holmes 的回答后,我在存储库方法中删除了一个可能导致问题的测试。不幸的是,问题仍然存在,仍然有 3 个查询正在执行,其中一个(或最多两个)就足够了。

最佳答案

Doctrine ODM 已经延迟加载引用的文档,而不是为您预取它。

我相信您的问题实际上在于您的存储库方法...例如,在 findOneByMetaData 函数中,您要做的第一件事是调用 $metadata->getArticle() 在执行此操作时,您要求教义从数据库中加载文章,由于您的 repositoryMethod 将再次调用 findOneByMetaData。这就是您看到多个查询的原因。

您的 findOneByMetaData 函数应该看起来更像这样:

// In the ArticleRepository
public function findOneByMetaData(ArticleMetaData $metadata)
{
$article = $this->createQueryBuilder()
->field('groupcode')->equals($metadata->getGroupcode())
->getQuery()
->getSingleResult();

$article->setMetaData($metadata);

return $article;
}

Doctrine 会处理文章是否已经加载,因此无需尝试检查是否有空值。这同样适用于您的 findOneByArticle 函数。

希望这有意义,并帮助您解决问题。

关于php - Doctrine ODM OneToOne Bi-Directional Reference using repositoryMethod,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27842533/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com