GQLAlchemy

repository·main·Indexed 43 days ago

https://github.com/memgraph/gqlalchemy

An 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.

Tokens
52.2K
Snippets
184
Records
235
Agent score
54%

What's inside GQLAlchemy

  1. What is GQLAlchemy

    main
    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.
  2. What is GQLAlchemy and how does it work?

    main

    GQLAlchemy 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.

  3. How GQLAlchemy translators work for Python graphs

    main

    GQLAlchemy 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)
  4. Transform Python graphs into Memgraph graphs

    main

    GQLAlchemy 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
  5. Configure data mapping for Many-to-Many relationships

    main

    For many-to-many relationships using an associative (junction) table, use the many_to_many_relations key 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 tenant table connecting individual and address with a duration property:

    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:
          - duration
  6. Map Table Names and Column Names

    main

    Use NameMappings and NameMapper to transform original table/column names into desired graph labels and properties.

    • NameMappings: Defines the transformation for a single table. Includes an optional label (the new graph label) and column_names_mapping (a dictionary mapping "original_column_name": "new_property_name").
    • NameMapper: A collection-wide mapper that manages NameMappings for all collections. It provides methods to retrieve the correct label and property name for any given collection and column.
  7. Use TFGNNTranslator to convert between Memgraph and TF-GNN

    main

    The TFGNNTranslator is used to convert between Memgraph graph representations and TensorFlow GNN (TF-GNN) GraphTensor objects. 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 a tfgnn.GraphTensor from 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()
  8. Handle retriable database errors with GQLAlchemyTransientError

    main

    When 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
        pass
  9. Use DeclarativeBase to construct Cypher queries

    main

    The DeclarativeBase class is the core component for building Cypher queries using a fluent Python API. It allows you to chain methods representing different Cypher clauses (like match(), create(), where(), return_()) to construct complex graph queries programmatically. Most methods return a DeclarativeBase instance, 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()
  10. How DGL graph translators work

    main

    The DGLTranslator class (imported from gqlalchemy.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 _N as the default node label and _E as the default relationship label.
      • Supports 1D and multidimensional features.
      • Note: Isolated nodes are not translated.
      • Nodes and relationships are assigned a dgl_id property for consistency.

    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 list are 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()
  11. Run failover-safe managed transactions

    main

    To ensure operations survive cluster failovers (e.g., when a new main is being elected), use execute_write() and execute_read().

    These methods take a work callable 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 work function is idempotent (e.g., use MERGE instead of CREATE).
    • Materialize Results: Wrap results in list(...) or similar before returning from the work function, as the transaction is closed immediately once work returns.
    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)