【发布时间】:2019-03-14 11:12:16
【问题描述】:
我一直在尝试减少 Web api 上的数据库查询数量。
我的数据库有 3 个集合:playground、widget、token
一个游乐场有很多小部件,一个小部件有一个令牌。每个关系使用referencesOne/referenceMany。
这是我的简化模型
/**
* @MongoDB\Document()
*/
class Widget
{
/**
* @MongoDB\ReferenceOne(targetDocument="Token", inversedBy="widgets")
*/
protected $token;
/**
* @MongoDB\ReferenceOne(targetDocument="Playground", inversedBy="widgets")
*/
protected $playground;
}
/**
* @MongoDB\Document()
*/
class Playground
{
/**
* @MongoDB\ReferenceMany(targetDocument="Widget", mappedBy="playground")
*/
protected $widgets;
}
/**
* @MongoDB\Document()
*/
class Token
{
/**
* @MongoDB\ReferenceMany(targetDocument="Widget", mappedBy="token")
*/
protected $widgets;
}
我需要使用完整的游乐场及其所有小部件和令牌,但默认情况下,Doctrine 会执行太多查询:一个获取游乐场(ok),一个获取映射的所有小部件(ok)和每个小部件,一个查询来获取令牌(不好)。有没有办法一次查询所有令牌而不是一个一个地获取它们?
我看过 prime,但它似乎没有解决我的问题...
除了使用查询生成器并手动对所有对象进行水合以减少查询计数之外,还有其他方法吗?
编辑: 正如我在评论中添加的那样,我正在寻找的是将游乐场及其所有依赖项作为一个大对象,对其进行 json 编码并将其返回到响应中。
我现在要做的是查询 Playground 并对其进行编码,但 Doctrine 以一种非有效的方式填充依赖项:首先是获取 playgroung 的查询,然后,还有一个获取相关小部件的查询是对每个小部件进行一次查询以获取其令牌。
由于一个 Playground 可以有数百个小部件,这会导致数百个数据库查询。
我正在寻找一种方法来告诉 Doctrine 仅使用 3 个查询(一个用于获取 playgroung,一个用于获取小部件,一个用于获取令牌)来获取所有这些数据。
【问题讨论】:
-
我不太明白这里的问题。您想要所有
Token在您的数据库中吗?您可以使用$tokenRepository->findAll();将所有Token和$tokenRepository->findBy(array $criteria);与$criteria一起作为您的查询参数。 -
@Etshy 不,我不是在寻找关于令牌的 findAll,我想要一个游乐场及其所有依赖项并将文档作为 json 返回。 Doctrine 没有以一种有效的方式查询数据库:它所做的是 1)获取游乐场,2)获取相关的小部件,3)对于每个小部件,获取相关的令牌。由于一个 Playground 可以有数百个小部件,这会导致数百个数据库查询。我正在寻找一种方法来告诉教义循环遍历所有游乐场小部件以获取相关的令牌 ID,然后一次获取所有令牌。这样无论有多少小部件,总会有 3 个查询。
-
哦,好的。我不确定你怎么能做到这一点。您可以尝试
findBy(['widgets.id' => $widgetsIds])之类的方法,其中$widgetsIds是一个ID 数组。我真的不确定findBy是否可以使用这样的数组。 -
你考虑过使用aggregate吗?因为在我看来,你所需要的只是一个聚合管道。
-
简单地编写一个自定义查询可能更简单,性能更高。
标签: php mongodb symfony doctrine-odm