Search by

packagefactory / neos-mysql-content-graph-queries

mhsdesign

Additional content graph queries for the MariaDB / MySQL content graph adapter

Package info

codeberg.org/PackageFactory/PackageFactory.Neos.MySqlContentGraphQueries

Issues

Type:neos-package

pkg:composer/packagefactory/neos-mysql-content-graph-queries

Statistics

Installs: 6

Dependents: 0

Suggesters: 0

0.1.2 2026-11-07 14:27 UTC

This package is auto-updated.

Last update: 2026-11-07 13:36:58 UTC


README

Provides additional content graph queries for the MariaDB / MySQL content graph adapter.

The idea is writing efficient queries that work on the Neos content graph by leveraging persistent indexes and by avoiding costly operations like CTEs and prefiltering results drastically. A variation of this package is in production use for a large Neos installation with more than 250K nodes.

This package is highly experimental and just a PoC. Further it requires currently a patch to set up.

Custom JSON property indexes and a query to find nodes by type independent of hierarchy should eventually become part of the Neos Core.

Making the Neos backend accessible with hundred thousand of nodes.

This package provides with the NodeType queries the possibility to efficiently query the graph bluntly ignoring hierarchy in any way because the joins are to expensive in my tests. Using these queries in combination with a flat-navigation document tree in the Neos Ui will make it possible to navigate a content graph of largest size:

https://discuss.neos.io/t/discussion-editing-and-storing-thousands-of-blog-posts-news-entries-in-nodes-in-neos-9-0/7154

Api - each a custom SQL query which is fast via indexes

findFirstChildNode()

The first idea was an optimised ContentSubgraphInterface::findChildNodes() via generated column for the "uriPathSegment" property

https://mariadb.com/docs/server/reference/sql-statements/data-definition/create/generated-columns

ALTER TABLE cr_default_p_graph_node 
  ADD COLUMN pf_uriPathSegment VARCHAR(255) COLLATE utf8mb4_unicode_520_ci AS (JSON_VALUE(properties, '$.uriPathSegment.value')) PERSISTENT;

CREATE INDEX idx_pf_uriPathSegment ON cr_default_p_graph_node(pf_uriPathSegment);

So we can replace

$subgraph->findChildNodes(
    $parentNodeAggregateId,
    FindChildNodesFilter::create(
        propertyValue: sprintf('uriPathSegment = \'%s\'', addslashes($uriPathSegment)),
        pagination: Pagination::fromLimitAndOffset(1, 0)
    )
)->first()

With a query ordering by n.idx_pf_uriPathSegment.

public function findFirstChildNode(
    WorkspaceName $workspaceName,
    DimensionSpacePoint $dimensionSpacePoint,
    VisibilityConstraints $visibilityConstraints,
    NodeAggregateId $parentNodeAggregateId,
    PropertyValueEquals::create(
        VirtualNodePropertyColumnName::fromString('pf_uriPathSegment'),
        $uriPathSegment,
    )
): ?Node;

findNodeAggregateIdsByNodeType()

public function findNodeAggregateIdsByNodeType(
    WorkspaceName $workspaceName,
    NodeTypeConstraint $nodeTypeConstraint,
    VisibilityConstraints $visibilityConstraints,
    NodeOrdering $nodeOrdering,
    Pagination $pagination,
    DateConstraint $dateConstraint,
): NodeAggregateIds;

findNodesByNodeType()

public function findNodesByNodeType(
    WorkspaceName $workspaceName,
    DimensionSpacePoint $dimensionSpacePoint,
    VisibilityConstraints $visibilityConstraints,
    NodeTypeConstraint $nodeTypeConstraint,
    NodeOrdering $nodeOrdering,
    Pagination $pagination,
    DateConstraint $dateConstraint,
): Nodes;

findRandomNodesByType()

public function findRandomNodesByType(
    WorkspaceName $workspaceName,
    DimensionSpacePoint $dimensionSpacePoint,
    VisibilityConstraints $visibilityConstraints,
    NodeTypeName $nodeTypeName,
    DateConstraint $dateConstraint,
    int $limit,
): Nodes;

Authors & Sponsors

  • Marc Henry Schultz

The research and development of this package was generously sponsored by https://capazunda.at