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.4.tar.gz (33.7 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.4-py3-none-any.whl (26.5 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for neo4j_extension-0.1.4.tar.gz
Algorithm Hash digest
SHA256 d30f0002b82b5051a5d92fcb40cff18e594a6961d164984afdbfb207ef2c931b
MD5 aef976f1783931d7abe2a95849393043
BLAKE2b-256 48fa1f556e7e0c5270b8f2cb4b84bdb09e16815d3b56b318101ff885bba58505

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for neo4j_extension-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 7e282b88cdc35beb6bab6dfe8bf9a3629b707da2d8a05f38bbf2d53221507d37
MD5 3019e32f7ee7e77c5d90e7ac858ebcc9
BLAKE2b-256 bc2503ac81654eec6d9a72b367df7d86ad6770599bf716d3a0608fac87ce8d0f

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