2

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永続化するときにそれを更新できます。ただし、これは、子を追加または削除するときに親を更新する必要があることも意味します。

この問題を解決するための指針はありますか?

4

1 に答える 1

4

私が知っている MongoDB で配列が空でないことをテストする最も効率的な方法は、「ドット表記」$exists. これには、クエリビルダーにアクセスできます。

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

これは、シェルの次と同じです。

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

配列0の最初の要素のインデックスも同様で、その配列にコンテンツがある場合にのみ存在します。空の配列はこの条件に一致しません。

于 2015-01-14T08:40:39.510 に答える