GQLAlchemy
repository·main·Indexed 43 days ago
https://github.com/memgraph/gqlalchemyAn Object Graph Mapper (OGM) for Python version 3.10+ that allows developers to interact with Memgraph graph databases using object-oriented code instead of raw Cypher queries. Version 1.10.0 includes support for high-availability cluster routing, managed transactions, and programmatic instance management via Docker or binary runners.
What's inside GQLAlchemy
- GQLAlchemy is an Object Graph Mapper (OGM) for Python. It acts as a bridge between graph database objects and Python objects, allowing developers to use object-oriented notation to interact with graph databases. The OGM automatically translates object-oriented code into Cypher queries, eliminating the need to write raw Cypher manually.
What is GQLAlchemy and how does it work?
mainGQLAlchemy is an Object Graph Mapper (OGM) for Python. It acts as a bridge between graph database objects (in Memgraph or Neo4j) and Python objects.
Instead of manually writing Cypher queries for every operation, an OGM allows you to use object-oriented notation to communicate with the database. The library then automatically translates your object-oriented code into the appropriate Cypher queries.
How GQLAlchemy translators work for Python graphs
mainGQLAlchemy provides translators that allow you to import various Python graph libraries into Memgraph. These translators take a Python graph object (from libraries like NetworkX, PyG, DGL, or TF-GNN) and convert them into Cypher queries. These queries are then executed against a Memgraph instance to reconstruct the graph structure and properties within the database.
Commonly supported libraries include:
- NetworkX
- PyG (PyTorch Geometric)
- DGL (Deep Graph Library)
- TF-GNN (TensorFlow GNN)
- DOT files (via NetworkX/pydot)
Transform Python graphs into Memgraph graphs
mainGQLAlchemy provides transformations to convert common Python graph objects into Memgraph graphs. The library translates the source graph object into Cypher queries and executes them in Memgraph.
Supported source graph types:
- NetworkX graphs
- PyG (PyTorch Geometric) graphs
- DGL (Deep Graph Library) graphs
Configure data mapping for Many-to-Many relationships
mainFor many-to-many relationships using an associative (junction) table, use the
many_to_many_relationskey in your configuration. This allows you to define two foreign keys (one for each side of the relationship) and optionally include properties from the associative table onto the resulting relationship edge.Key fields for
many_to_many_relations:foreign_key_from: The source side of the relationship.foreign_key_to: The destination side of the relationship.label: The relationship type.properties: A list of column names from the associative table to be added as properties to the edge.
Example YAML configuration for a
tenanttable connectingindividualandaddresswith adurationproperty:indices: address: - add_id individual: - ind_id name_mappings: individual: label: INDIVIDUAL address: label: ADDRESS tenant: column_names_mapping: duration: years one_to_many_relations: address: [] individual: [] many_to_many_relations: tenant: foreign_key_from: column_name: ind_id reference_table: individual reference_key: ind_id foreign_key_to: column_name: add_id reference_table: address reference_key: add_id label: LIVES_IN properties: - durationMap Table Names and Column Names
mainUse
NameMappingsandNameMapperto transform original table/column names into desired graph labels and properties.NameMappings: Defines the transformation for a single table. Includes an optionallabel(the new graph label) andcolumn_names_mapping(a dictionary mapping"original_column_name": "new_property_name").NameMapper: A collection-wide mapper that managesNameMappingsfor all collections. It provides methods to retrieve the correct label and property name for any given collection and column.
Use TFGNNTranslator to convert between Memgraph and TF-GNN
mainThe
TFGNNTranslatoris used to convert between Memgraph graph representations and TensorFlow GNN (TF-GNN)GraphTensorobjects. TF-GNN represents graphs as composite tensors suitable for TensorFlow and Keras operations, supporting both homogeneous and heterogeneous graphs with node and edge features.Converting Memgraph to TF-GNN
Use
get_instance()to create atfgnn.GraphTensorfrom all nodes and edges currently in Memgraph. The translator maps Memgraph node labels to TF-GNN node sets and edge types to edge sets.Property Conversion Rules:
- String, Integer, Float, Boolean: Converted to corresponding TensorFlow dtypes.
- Lists: Converted to tensors (dense if all elements have the same length, ragged if lengths vary).
- Missing properties: Result in ragged tensors with empty values.
- Memgraph-specific types (temporal, Enum, Point): Converted to their string representation.
- Map properties: Not supported and will raise an error.
from gqlalchemy.transformations.translators.tfgnn_translator import TFGNNTranslator translator = TFGNNTranslator() # Create a GraphTensor from the current Memgraph state graph_tensor = translator.get_instance()Handle retriable database errors with GQLAlchemyTransientError
mainWhen interacting with the database, you may encounter
GQLAlchemyTransientError. This exception represents a database error that is temporary and worth retrying (e.g., network blips or temporary unavailability). You should implement retry logic when catching this specific error type to improve application resilience.try: # Perform database operation pass except GQLAlchemyTransientError: # Implement retry logic here passUse DeclarativeBase to construct Cypher queries
mainThe
DeclarativeBaseclass is the core component for building Cypher queries using a fluent Python API. It allows you to chain methods representing different Cypher clauses (likematch(),create(),where(),return_()) to construct complex graph queries programmatically. Most methods return aDeclarativeBaseinstance, enabling method chaining, and the process is finalized by calling.execute()to run the query against the database.# Example of a complete query chain results = match().node(labels='Person', variable='p').return_().execute()How DGL graph translators work
mainThe
DGLTranslatorclass (imported fromgqlalchemy.transformations.translators.dgl_translator) facilitates translation between Deep Graph Library (DGL) graphs and Memgraph.Importing (DGL $\rightarrow$ Memgraph):
to_cypher_queries(dgl_graph): Generates Cypher queries for homogeneous and heterogeneous graphs.- For homogeneous graphs, it uses
_Nas the default node label and_Eas the default relationship label. - Supports 1D and multidimensional features.
- Note: Isolated nodes are not translated.
- Nodes and relationships are assigned a
dgl_idproperty for consistency.
- For homogeneous graphs, it uses
Exporting (Memgraph $\rightarrow$ DGL):
get_instance(): Returns a DGL heterograph instance.- Note: Isolated nodes are ignored.
- Only numerical properties that are present on all nodes and relationships are translated.
- String properties and non-uniform numerical properties are excluded.
- Properties of type
listare translated as features.
# Import DGL from gqlalchemy.transformations.translators.dgl_translator import DGLTranslator # Import to Memgraph for query in DGLTranslator().to_cypher_queries(dgl_graph): memgraph.execute(query) # Export from Memgraph graph = DGLTranslator().get_instance()Use On-disk storage for large properties
mainSince Memgraph is an in-memory database, GQLAlchemy provides an on-disk storage solution. This is intended for storing large properties that do not need to be accessed by graph algorithms, helping to manage memory usage.Run failover-safe managed transactions
mainTo ensure operations survive cluster failovers (e.g., when a new main is being elected), use
execute_write()andexecute_read().These methods take a
workcallable that receives a transaction object. GQLAlchemy handles routing and automatically retries the transaction if the cluster is in flux.Important Best Practices:
- Idempotency: Because a managed transaction may run more than once during retries, ensure your
workfunction is idempotent (e.g., useMERGEinstead ofCREATE). - Materialize Results: Wrap results in
list(...)or similar before returning from theworkfunction, as the transaction is closed immediately onceworkreturns.
from gqlalchemy import Memgraph db = Memgraph(host="coordinator-1", port=7687, routing=True) # Managed write transaction def add_person(tx): tx.execute("MERGE (:Person {name: $name})", {"name": "Ada"}) # Materialize results before returning rows = list(tx.execute_and_fetch("MATCH (n:Person) RETURN count(n) AS count")) return rows[0]["count"] count = db.execute_write(add_person) # Managed read transaction def count_people(tx): rows = list(tx.execute_and_fetch("MATCH (:Person) RETURN count(*) AS count")) return rows[0]["count"] total = db.execute_read(count_people)- Idempotency: Because a managed transaction may run more than once during retries, ensure your