我正在尝试使用Doctrine MongoDB构建一个延迟加载树。 我的文件结构如下:
/**
* @ODM\Document(repositoryClass="CmsPage\Repository\PageRepository")
*/
class Page
{
/**
* @ODM\String
* @var string
*/
protected $title;
/**
* @ODM\ReferenceOne(targetDocument="CmsPage\Document\Page", inversedBy="children")
* @ODM\Index
* @var Page
*/
protected $parent;
/**
* @ODM\ReferenceMany(
* targetDocument="CmsPage\Document\Page", mappedBy="parent",
* sort={"title": "asc"}
* )
* @var array
*/
protected $children;
/**
* Default constructor
*/
public function __construct()
{
$this->children = new ArrayCollection();
}
/**
* @return ArrayCollection|Page[]
*/
public function getChildren()
{
return $this->children;
}
/**
* @param ArrayCollection $children
*/
public function setChildren($children)
{
$this->children = $children;
}
/**
* @return Page
*/
public function getParent()
{
return $this->parent;
}
/**
* @param Page $parent
*/
public function setParent($parent)
{
$this->parent = $parent;
}
/**
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* @param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
}
以下代码将检索给定页面的所有子项:
$page = $pageRepo->find('foo');
$children = [];
foreach ($page->getChildren() as $childPage) {
$children[] = [
'id' => $childPage->getId(),
'slug' => $childPage->getSlug(),
'leaf' => ($childPage->getChildren()->count() == 0)
];
这是按预期工作的,但会对每个子页面执行单独的查询以检查它是否为叶子。当处理具有大量子节点的大树时,它将不会有效。
我可以在我的Page文档中引入一个布尔isLeaf
并在持久化时更新它。但这也意味着我必须在添加或删除子项时更新父项。
你有什么指针可以解决这个问题吗?
答案 0 :(得分:3)
我知道在MongoDB中测试数组不为空的最有效方法是搜索"第一个"使用"dot notation"和$exists
的数组中的元素。 query builder可以访问:
$qb = $dm->createQueryBuilder('Page')
->field('children.0')->exists(true);
这与shell中的相同:
db.collection.find({ "children.0": { "$exists": true } })
所以0
是数组中第一个元素的索引,只有在该数组中有一些内容时才会出现。空数组与此条件不匹配。