Skip to main content

Define types for Neo4j

Project description

neo4j-extension

A Python library that provides higher-level abstractions and utilities for working with Neo4j databases. It wraps the official Neo4j Python driver to simplify both synchronous and asynchronous operations, offers object-like handling of Nodes and Relationships, and includes a system for dealing with Neo4j types (dates, times, durations, spatial data, etc.) in a Pythonic way.

Table of Contents


Features

  1. Neo4jConnection

    • A high-level connection class that manages the underlying neo4j.Driver (for sync) or neo4j.AsyncDriver (for async).
    • Supports environment variables to configure host, port, user, and password:
      • NEO4J_HOST (default "localhost")
      • NEO4J_BOLT_PORT (default "7687")
      • NEO4J_USER (default "neo4j")
      • NEO4J_PASSWORD (default "")
  2. Schema Extraction

    • Quickly retrieve the database schema (labels, relationship types, properties, and indexes/constraints) via get_graph_schema() or get_formatted_graph_schema().
  3. Transaction Decorators

    • Decorators for simpler read-write or read-only transactions, both sync and async:
      • @with_session.readwrite_transaction
      • @with_session.readonly_transaction
      • @with_async_session.readwrite_transaction
      • @with_async_session.readonly_transaction
  4. Graph Model Classes

    • Graph, Node, Relationship classes to represent and manipulate graph elements in Python.
    • upsert_node, upsert_relationship, and upsert_graph methods to persist changes to Neo4j.
  5. Neo4jType System

    • Abstract base class Neo4jType and concrete classes (e.g. Neo4jString, Neo4jInteger, Neo4jBoolean, Neo4jPoint, etc.) represent Neo4j values with serialization/deserialization into Cypher syntax.
    • Functions for converting back and forth between native Python objects and these Neo4jType classes.

Installation

pip install neo4j-extension@git+https://github.com/c0sogi/neo4j-extension.git

Quick Start

Below is a minimal example of establishing a connection, creating nodes/relationships, and reading the schema.

from neo4j_extension import Neo4jConnection, Graph, Node, Relationship

# Initialize connection (can also rely on environment variables)
conn = Neo4jConnection(
    host="localhost",
    port="7687",
    user="neo4j",
    password="secret"
)

# Connect to Neo4j (driver is lazily loaded; you can force initialization here)
driver = conn.connect()

# Clear all data from the database (dangerous in production!)
conn.clear_all()

# Create a small graph
g = Graph()
node1 = Node(properties={"name": "Alice", "age": 30}, labels={"Person"}, globalId="node1")
node2 = Node(properties={"name": "Bob", "age": 25}, labels={"Person"}, globalId="node2")
rel   = Relationship(properties={"since": 2020}, rel_type="KNOWS", start_node=node1, end_node=node2, globalId="rel1")

g.add_node(node1)
g.add_node(node2)
g.add_relationship(rel)

# Upsert the entire Graph into Neo4j
conn.upsert_graph(g)

# Print the schema discovered from the database
print(conn.get_formatted_graph_schema())

# Close the connection
conn.close()

Usage Examples

Basic Connection

from neo4j_extension import Neo4jConnection

# Provide credentials directly
conn = Neo4jConnection(
    host="my_neo4j_host",
    port="7687",
    user="neo4j",
    password="secret_password"
)

# Or rely on environment variables (NEO4J_HOST, NEO4J_BOLT_PORT, etc.)
with Neo4jConnection() as conn:
  ...  # Use the connection here

# You can also use the async context manager
async with Neo4jConnection() as conn:
  ...  # Use the async connection here

Retrieving the Graph Schema

# Retrieve a structured dictionary with node props, rel props, relationships, and metadata
schema = conn.get_graph_schema()
print(schema)

# Or get a human-readable formatted output
print(conn.get_formatted_graph_schema())

Working with Nodes and Relationships

from neo4j_extension import Graph, Node, Relationship

# Build up a small graph in memory
g = Graph()

node_alice = Node(properties={"name": "Alice"}, labels={"Person"}, globalId="alice")
node_bob   = Node(properties={"name": "Bob"},   labels={"Person"}, globalId="bob")
rel        = Relationship(
    properties={"since": 2021},
    rel_type="KNOWS",
    start_node=node_alice,
    end_node=node_bob,
    globalId="rel_alice_knows_bob"
)

g.add_node(node_alice)
g.add_node(node_bob)
g.add_relationship(rel)

# Use upsert_graph to write everything in a single transaction
conn.upsert_graph(g)

Some Handy Utility Methods

In addition to creating/upserting Node and Relationship objects, Neo4jConnection includes many convenience methods for everyday tasks:

  • Node / Relationship Lookups

    • find_node_by_global_id(gid) : Get a single node by its globalId
    • match_nodes(label, property_filters=None, limit=None) : Find nodes by label and optional property filters
    • match_relationships(rel_type, property_filters=None, limit=None) : Same pattern for relationships
    • find_nodes_in_relationship(rel_type, property_filters=None, limit=None) : Returns (start_node, relationship, end_node) tuples
  • Deletion

    • delete_node_by_global_id(gid) : Detach and delete a single node
    • delete_nodes_by_label(label, property_filters=None) : Detach and delete multiple nodes
    • delete_relationship_by_global_id(gid) : Delete a single relationship
    • delete_relationships_by_type(rel_type, property_filters=None) : Delete multiple relationships
  • Updating Node / Relationship Data

    • update_node_properties(gid, new_properties) : Add or overwrite properties on a node
    • remove_node_property(gid, property_key) : Remove one property
    • add_labels_to_node(gid, labels) / remove_labels_from_node(gid, labels) : Manage labels
    • update_relationship_properties(gid, new_properties) : Add or overwrite properties on a relationship
  • Linking Nodes

    • link_nodes(start_gid, end_gid, rel_type, properties=None) : Merge or create a relationship between two existing nodes
  • Inspecting Existing Data

    • get_node_properties(gid) / get_relationship_properties(gid) : Return a dict of properties
    • count_nodes(label) / count_relationships(rel_type) : Quickly get counts of labeled nodes or typed relationships

These utilities all use the same transaction decorators behind the scenes, so you can focus on your logic rather than boilerplate Cypher queries.

Synchronous vs. Asynchronous

  • Synchronous (uses @with_session decorators):

    from neo4j_extension import Neo4jConnection, with_session
    from neo4j import ManagedTransaction
    
    class MyNeo4j(Neo4jConnection):
        @with_session.readwrite_transaction
        def create_person(self, tx: ManagedTransaction, name: str):
            query = "CREATE (p:Person {name: $name}) RETURN p"
            tx.run(query, name=name)
    
    my_conn = MyNeo4j()
    my_conn.create_person("Alice")
    my_conn.close()
    
  • Asynchronous (uses @with_async_session decorators):

    import asyncio
    from neo4j_extension import Neo4jConnection, with_async_session
    from neo4j import AsyncManagedTransaction
    
    class MyAsyncNeo4j(Neo4jConnection):
        @with_async_session.readwrite_transaction
        async def create_person_async(self, tx: AsyncManagedTransaction, name: str):
            query = "CREATE (p:Person {name: $name}) RETURN p"
            await tx.run(query, name=name)
    
    async def main():
        my_conn = MyAsyncNeo4j()
        await my_conn.create_person_async("Alice")
        await my_conn.aclose()
    
    asyncio.run(main())
    

Neo4j Types

This library defines an extensive set of classes to represent Neo4j data types in Python. They inherit from the abstract base Neo4jType and implement methods like to_cypher() and from_cypher() for serialization/deserialization:

  • Primitives: Neo4jNull, Neo4jBoolean, Neo4jInteger, Neo4jFloat, Neo4jString
  • Containers: Neo4jList, Neo4jMap
  • Spatial: Neo4jPoint (with PointValue)
  • Temporal: Neo4jDate, Neo4jLocalTime, Neo4jLocalDateTime, Neo4jZonedTime, Neo4jZonedDateTime, Neo4jDuration
  • Binary: Neo4jByteArray

You can convert a Cypher expression string to a Neo4jType with convert_cypher_to_neo4j(expr) and convert between Python native values and Neo4jType objects via ensure_neo4j_type(value) or convert_neo4j_to_python(value).


License

MIT License


Enjoy using neo4j_extension to simplify your Neo4j workflows!

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

neo4j_extension-0.1.14.tar.gz (46.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

neo4j_extension-0.1.14-py3-none-any.whl (35.7 kB view details)

Uploaded Python 3

File details

Details for the file neo4j_extension-0.1.14.tar.gz.

File metadata

  • Download URL: neo4j_extension-0.1.14.tar.gz
  • Upload date:
  • Size: 46.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.21

File hashes

Hashes for neo4j_extension-0.1.14.tar.gz
Algorithm Hash digest
SHA256 10c17f7f856316ba827caf064c44d01f64ffbead78d61e91921ed852ad76f901
MD5 7e241f8f7629964fe0af7c0eee6898c1
BLAKE2b-256 c8d8bd752c2c19e54652bd731abc46054232a83c1a23e5dfd6a0dda33216c42e

See more details on using hashes here.

File details

Details for the file neo4j_extension-0.1.14-py3-none-any.whl.

File metadata

File hashes

Hashes for neo4j_extension-0.1.14-py3-none-any.whl
Algorithm Hash digest
SHA256 e267f567a6a28e109dfa1d28a312fd34f1df6f76916857d57a435e648649ef67
MD5 b8f11e4dc3bd6320ea7909b34e53a1fd
BLAKE2b-256 c933dd23510a9d1deb1cdf0b397f8d733f7a88b39917b10f1440c2a50df3f82f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page