You are browsing a version that has not yet been released. |
Trees
MongoDB lends itself quite well to storing hierarchical data. This chapter will demonstrate some examples!
Full Tree in Single Document
<?php
#[Document]
class BlogPost
{
#[Id]
private string $id;
#[Field(type: 'string')]
private string $title;
#[Field(type: 'string')]
private string $body;
/** @var Collection<Comment> */
#[EmbedMany(targetDocument: Comment::class)]
private Collection $comments;
// ...
}
#[EmbeddedDocument]
class Comment
{
#[Field(type: 'string')]
private string $by;
#[Field(type: 'string')]
private string $text;
/** @var Collection<Comment> */
#[EmbedMany(targetDocument: Comment::class)]
private Collection $replies;
// ...
}
Retrieve a blog post and only select the first 10 comments:
<?php
$post = $dm->createQueryBuilder(BlogPost::class)
->selectSlice('replies', 0, 10)
->getQuery()
->getSingleResult();
$replies = $post->getReplies();
You can read more about this pattern on the MongoDB documentation page "Trees in MongoDB" in the Full Tree in Single Document section.
Parent Reference
<?php
#[Document]
class Category
{
#[Id]
private string $id;
#[Field(type: 'string')]
private string $name;
#[ReferenceOne(targetDocument: Category::class)]
#[Index]
private ?Category $parent = null;
// ...
}
Query for children by a specific parent id:
<?php
$children = $dm->createQueryBuilder(Category::class)
->field('parent.id')->equals('theid')
->getQuery()
->execute();
You can read more about this pattern on the MongoDB documentation page "Trees in MongoDB" in the Parent Links section.
Child Reference
<?php
#[Document]
class Category
{
#[Id]
private string $id;
#[Field(type: 'string')]
private string $name;
/** @var Collection<Category> */
#[ReferenceMany(targetDocument: Category::class)]
#[Index]
private Collection $children;
// ...
}
Query for immediate children of a category:
<?php
$category = $dm->createQueryBuilder(Category::class)
->field('id')->equals('theid')
->getQuery()
->getSingleResult();
$children = $category->getChildren();
Query for immediate parent of a category:
<?php
$parent = $dm->createQueryBuilder(Category::class)
->field('children.id')->equals('theid')
->getQuery()
->getSingleResult();
You can read more about this pattern on the MongoDB documentation page "Trees in MongoDB" in the Child Links section.
Array of Ancestors
<?php
#[MappedSuperclass]
class BaseCategory
{
#[Field(type: 'string')]
private string $name;
// ...
}
#[Document]
class Category extends BaseCategory
{
#[Id]
private string $id;
/** @var Collection<Category> */
#[ReferenceMany(targetDocument: Category::class)]
#[Index]
private Collection $ancestors;
/** @var Collection<Category> */
#[ReferenceOne(targetDocument: Category::class)]
#[Index]
private ?Category $parent = null;
// ...
}
#[EmbeddedDocument]
class SubCategory extends BaseCategory
{
}
Query for all descendants of a category:
<?php
$categories = $dm->createQueryBuilder(Category::class)
->field('ancestors.id')->equals('theid')
->getQuery()
->execute();
Query for all ancestors of a category:
<?php
$category = $dm->createQuery(Category::class)
->field('id')->equals('theid')
->getQuery()
->getSingleResult();
$ancestors = $category->getAncestors();
You can read more about this pattern on the MongoDB documentation page "Trees in MongoDB" in the Array of Ancestors section.
Materialized Paths
<?php
#[Document]
class Category
{
#[Id]
private string $id;
#[Field(type: 'string')]
private string $name;
#[Field(type: 'string')]
private string $path;
// ...
}
Query for the entire tree:
<?php
$categories = $dm->createQuery(Category::class)
->sort('path', 'asc')
->getQuery()
->execute();
Query for the node 'b' and all its descendants:
<?php
$categories = $dm->createQuery(Category::class)
->field('path')->equals('/^a,b,/')
->getQuery()
->execute();
You can read more about this pattern on the MongoDB documentation page "Trees in MongoDB" in the Materialized Paths (Full Path in Each Node) section.