packagefactory / neos-mysql-content-graph-queries
Additional content graph queries for the MariaDB / MySQL content graph adapter
Package info
codeberg.org/PackageFactory/PackageFactory.Neos.MySqlContentGraphQueries
Type:neos-package
pkg:composer/packagefactory/neos-mysql-content-graph-queries
Requires
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
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:
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