Эффективно проверьте, есть ли у документа дети

Я пытаюсь построить ленивое дерево загрузки, используя 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)
];

Это работает, как и ожидалось, но выполнит отдельный запрос для каждой дочерней страницы, чтобы проверить, является ли это листом. При работе с большим деревом с большим количеством дочерних узлов это будет неэффективно.

Я мог бы ввести логическое значение isLeaf в моей странице документа и обновите его при сохранении. Но это также означает, что я должен обновить родителя при добавлении или удалении ребенка.

У вас есть какие-либо указатели, чтобы решить эту проблему?

2

Решение

Наиболее эффективный способ, который я знаю в MongoDB для проверки того, что массив не пуст, — это поиск наличия «первого» элемента в массиве с использованием «точечная нотация» а также $exists. Есть доступ в построитель запросов за это:

$qb = $dm->createQueryBuilder('Page')
->field('children.0')->exists(true);

Это то же самое, что и в оболочке:

db.collection.find({ "children.0": { "$exists": true } })

Так 0 является индексом первого элемента в массиве и присутствует, только если в этом массиве есть некоторый контент. Пустые массивы не соответствуют этому условию.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]