Doctrine 2 - 如何在没有递归的情况下将整个数据集加载到无向图的缓存中?

问题描述 投票:0回答:1

我们有一个我认为不是不寻常的实体

Foo
用例,它可以有任意数量的父母和孩子
Foo
s。这是通过一个
FooRelations
实体实现的,它有一个父实体
Foo
和一个子实体
Foo
Foo
具有名为
manyToOne
childFoos
parentFoos
关系,它们被设置为
EAGER
.

因为图表很复杂,尝试加载完整的

Foo
会导致数以千计的数据库查询/行程 - 加载
Foo
(一个查询),加载所有
Foo
的孩子(一个查询),为每个孩子
Foo
,在两个方向加载它的所有子项(每个一个查询)等等。

图表并没有那么复杂或庞大,总共大约有 5000

Foo
s。
Foo
s 也很小,我们谈论的是整个表的总计几 KB 的数据。我们只想说“加载所有
Foo
,然后加载
FooRelations
并填充所有对象。相反,所有
Foo
都有
AbstractLazyCollection
作为
getChildren
/
getParent
,尽管
EAGER
标志在访问之前不会被填充。

我们做错了什么吗?有没有办法完成我们在这里要做的事情?加载数据本身与

SELECT f, p, c FROM Foo::class LEFT JOIN f.parent p LEFT JOIN f.child c
类似,因此查询数据不是问题,只需将其保存在缓存中即可。

php graph doctrine-orm doctrine hierarchy
1个回答
0
投票

由于事先不知道层次结构的深度,你最终总会有一些重复出现的逻辑。您可以通过递归实现这一点这一事实意味着您可以通过 stack 实现您的结果,尽管如果您使用递归,那么您使用的堆栈是内存中堆叠函数调用的一部分,称为 stack .您可以将算法转换为迭代算法。因此,您可以显式使用堆栈并执行如下操作,而不是自调用函数:

//$stack is a properly initialized empty stack
//$tree is a properly built tree where your hierarchy is stored
$stackItems = getNodesByParentID(null);
foreach ($stackItems as $stackItem) $stack->push($stackItem);
while (!$stack->isEmpty()) {
    $stackNode = $stack->pop();
    //The following two lines appeal to find and add, methods that are
    //assumed to be implemented, but they are less relevance to the point
    //of the question, so I will assume you have no trouble implementing them
    $parentNode = find($tree, $stackNode->parentID);
    add($tree, $stackNode);
    $stackItems = getNodesByParentID($stackNode->parentID);
    foreach ($stackItems as $stackItem) $stack->push($stackItem);
}

本质上,您在算法上执行类似于递归的操作,而您使用的是堆内存而不是堆栈内存,并且您的算法是迭代的。

然而,您将需要考虑其他问题,例如图表中的循环或损坏的数据。为了简单起见,我暂时忽略了这些问题,但它们肯定是可以解决的。

© www.soinside.com 2019 - 2024. All rights reserved.