diff --git a/mage/query-modules/cpp/meta.md b/mage/query-modules/cpp/meta.md new file mode 100644 index 00000000000..98569b59379 --- /dev/null +++ b/mage/query-modules/cpp/meta.md @@ -0,0 +1,178 @@ +--- +id: meta +title: meta +sidebar_label: meta +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import RunOnSubgraph from '../../templates/_run_on_subgraph.mdx'; + +export const Highlight = ({children, color}) => ( + +{children} + +); + + +The **meta** module provides a set of procedures for generating metadata about the database. + +[![docs-source](https://img.shields.io/badge/source-util_module-FB6E00?logo=github&style=for-the-badge)](https://github.com/memgraph/mage/tree/main/cpp/meta_module) + +| Trait | Value | +| ------------------- | ----------------------------------------------------- | +| **Module type** | **algorithm** | +| **Implementation** | **C++** | +| **Parallelism** | **parallel** | + +### Procedures + +### `stats_online(update_stats)` + +Retrieves the graph metadata in **O(1)** complexity. Requires setting up the following trigger: + + ```cypher + CREATE TRIGGER meta_trigger BEFORE COMMIT EXECUTE CALL meta.update(createdObjects, deletedObjects, removedVertexProperties, removedEdgeProperties, setVertexLabels, removedVertexLabels); + ``` + +This procedure tracks the data created/deleted/modified after the trigger was added. If you want to return the metadata about the whole graph you need to run the *stats_online* procedure with the *update_stats* flag set to true **once**. That flag will cause the procedure to traverse the whole graph to update the metadata. After that you can always run with the *update_stats* flag set to false and the procedure will return the metadata in **O(1)** complexity. + +#### Input: + +- `update_stats: bool (default=false)` ➡ if true traverses the whole graph to update the metadata otherwise returns the stored metadata. + +#### Output: + +- `labelCount: int` ➡ number of unique labels in nodes. +- `relationshipTypeCount: int` ➡ number of unique relationship types (labels). +- `nodeCount: int` ➡ number of nodes in the graph. +- `relationshipCount: int` ➡ number of relationships in the graph. +- `labels: Map[string: int]` ➡ map with the following (key, value) pairs: + - `label` : number_of_occurrences +- `relationshipTypes: Map[string: int]` ➡ map with the following (key, value) pairs: + - `(:label)-[:relationship_type]->()` : number_of_occurrences + - `()-[:relationship_type]->(:label)` : number_of_occurrences + - `()-[:relationship_type]->()` : number_of_occurrences +- `relationshipTypesCount: Map[string: int]` ➡ map with the following (key, value) pairs: + - `relationship_type` : number_of_occurrences +- `stats` ➡ map which contains all of the above. + +#### Usage: + +Running stats on the following graph: +```cypher +MERGE (a:Node {id: 0}) MERGE (b:Node {id: 1}) CREATE (a)-[:Relation1]->(b); +MERGE (a:Node {id: 1}) MERGE (b:Node {id: 2}) CREATE (a)-[:Relation1]->(b); +MERGE (a:Node {id: 2}) MERGE (b:Node {id: 0}) CREATE (a)-[:Relation1]->(b); +MERGE (a:Node {id: 3}) MERGE (b:Node {id: 3}) CREATE (a)-[:Relation2]->(b); +MERGE (a:Node {id: 3}) MERGE (b:Node {id: 4}) CREATE (a)-[:Relation2]->(b); +MERGE (a:Node {id: 3}) MERGE (b:Node {id: 5}) CREATE (a)-[:Relation2]->(b); +``` + +```cypher +CALL meta.stats_online() YIELD stats; +``` + +```plaintext ++-------------------------------------------------------+ +| stats | ++-------------------------------------------------------+ +| | +|{ | +| "labelCount": 1, | +| "labels": { | +| "Node": 6 | +| }, | +| "nodeCount": 6, | +| "propertyKeyCount": 1, | +| "relationshipCount": 6, | +| "relationshipTypeCount": 2, | +| "relationshipTypes": { | +| "()-[:Relation1]->()": 3, | +| "()-[:Relation1]->(:Node)": 3, | +| "()-[:Relation2]->()": 3, | +| "()-[:Relation2]->(:Node)": 3, | +| "(:Node)-[:Relation1]->()": 3, | +| "(:Node)-[:Relation2]->()": 3 | +| }, | +| "relationshipTypesCount": { | +| "Relation1": 3, | +| "Relation2": 3 | +| } | +|} | +| | ++-------------------------------------------------------+ +``` + +### `stats_offline()` + +Retrieves the graph metadata by traversing the whole graph. `stats_online` should be preferred because of the better complexity unless you don't want to use triggers. + +#### Output: + +- `labelCount: int` ➡ number of unique labels in nodes. +- `relationshipTypeCount: int` ➡ number of unique relationship types (labels). +- `nodeCount: int` ➡ number of nodes in the graph. +- `relationshipCount: int` ➡ number of relationships in the graph. +- `labels: Map[string: int]` ➡ map with the following (key, value) pairs: + - `label` : number_of_occurrences +- `relationshipTypes: Map[string: int]` ➡ map with the following (key, value) pairs: + - `(:label)-[:relationship_type]->()` : number_of_occurrences + - `()-[:relationship_type]->(:label)` : number_of_occurrences + - `()-[:relationship_type]->()` : number_of_occurrences +- `relationshipTypesCount: Map[string: int]` ➡ map with the following (key, value) pairs: + - `relationship_type` : number_of_occurrences +- `stats` ➡ map which contains all of the above. + +#### Usage: + +Running stats on the following graph: +```cypher +MERGE (a:Node {id: 0}) MERGE (b:Node {id: 1}) CREATE (a)-[:Relation1]->(b); +MERGE (a:Node {id: 1}) MERGE (b:Node {id: 2}) CREATE (a)-[:Relation1]->(b); +MERGE (a:Node {id: 2}) MERGE (b:Node {id: 0}) CREATE (a)-[:Relation1]->(b); +MERGE (a:Node {id: 3}) MERGE (b:Node {id: 3}) CREATE (a)-[:Relation2]->(b); +MERGE (a:Node {id: 3}) MERGE (b:Node {id: 4}) CREATE (a)-[:Relation2]->(b); +MERGE (a:Node {id: 3}) MERGE (b:Node {id: 5}) CREATE (a)-[:Relation2]->(b); +``` + +```cypher +CALL meta.stats_offline() YIELD stats; +``` + +```plaintext ++-------------------------------------------------------+ +| stats | ++-------------------------------------------------------+ +| | +|{ | +| "labelCount": 1, | +| "labels": { | +| "Node": 6 | +| }, | +| "nodeCount": 6, | +| "propertyKeyCount": 1, | +| "relationshipCount": 6, | +| "relationshipTypeCount": 2, | +| "relationshipTypes": { | +| "()-[:Relation1]->()": 3, | +| "()-[:Relation1]->(:Node)": 3, | +| "()-[:Relation2]->()": 3, | +| "()-[:Relation2]->(:Node)": 3, | +| "(:Node)-[:Relation1]->()": 3, | +| "(:Node)-[:Relation2]->()": 3 | +| }, | +| "relationshipTypesCount": { | +| "Relation1": 3, | +| "Relation2": 3 | +| } | +|} | +| | ++-------------------------------------------------------+ +``` diff --git a/mage/templates/_mage_spells.mdx b/mage/templates/_mage_spells.mdx index c5010a8e4a0..a24547717f3 100644 --- a/mage/templates/_mage_spells.mdx +++ b/mage/templates/_mage_spells.mdx @@ -60,6 +60,7 @@ | [import_util](/mage/query-modules/python/import-util) | Python | A module for importing data from different formats (JSON). | | [json_util](/mage/query-modules/python/json-util) | Python | A module for loading JSON from a local file or remote address. | | [llm_util](/mage/query-modules/python/llm-util) | Python | A module that contains procedures describing graphs in a format best suited for large language models (LLMs). | +| [meta](/mage/query-modules/cpp/meta) | C++ | A module that contains procedures describing graphs on a meta-level. | | [meta_util](/mage/query-modules/python/meta-util) | Python | A module that contains procedures describing graphs on a meta-level. | | [migrate](/mage/query-modules/python/migrate) | Python | A module that can access data from a MySQL, SQL Server or Oracle database. | | [periodic](/mage/query-modules/cpp/periodic) | C++ | A module containing procedures for periodically running difficult and/or memory/time consuming queries. | diff --git a/sidebars/sidebarsMAGE.js b/sidebars/sidebarsMAGE.js index c7b359cf431..c82ea7b311d 100644 --- a/sidebars/sidebarsMAGE.js +++ b/sidebars/sidebarsMAGE.js @@ -52,6 +52,7 @@ module.exports = { "query-modules/python/llm-util", "query-modules/cpp/map", "query-modules/python/max-flow", + "query-modules/cpp/meta", "query-modules/python/meta-util", "query-modules/python/migrate", "query-modules/python/node-classification-with-gnn",