OpenCypher PetGraph - 100% openCypher-compliant graph database engine
Project description
ocpg - OpenCypher PetGraph
ocpg is the Python package for nxcypher, a 100% openCypher-compliant graph database engine written in Rust.
OpenCypher + PetGraph = Fast, memory-safe graph queries in Python.
Features
- ✅ 100% openCypher TCK compliant (3,893 scenarios passing)
- 🚀 High performance - Pure Rust implementation with Python bindings
- 🔒 Memory safe - No unsafe code, guaranteed by Rust
- 🧪 Well tested - Comprehensive test coverage
- 📦 Easy to install - Single
pip installcommand - 🐍 Pythonic API - Natural Python interface
Installation
pip install ocpg
Quick Start
import ocpg
# Create a graph
g = ocpg.Graph()
# Create nodes and relationships
g.execute("""
CREATE (alice:Person {name: 'Alice', age: 30})
CREATE (bob:Person {name: 'Bob', age: 25})
CREATE (alice)-[:KNOWS]->(bob)
""")
# Query the graph
result = g.execute("MATCH (p:Person) RETURN p.name, p.age ORDER BY p.age")
# Iterate over results
for row in result:
print(f"Name: {row['p.name']}, Age: {row['p.age']}")
# Or convert to list
data = result.to_list()
print(data)
API Reference
Graph
The main graph database class.
Methods
-
execute(query: str, params: dict = None) -> QueryResultExecute a Cypher query with optional parameters.
result = g.execute( "MATCH (n:Person) WHERE n.age > $min_age RETURN n", {"min_age": 18} )
-
node_count() -> intGet the number of nodes in the graph.
-
edge_count() -> intGet the number of relationships in the graph.
-
clear()Remove all nodes and relationships from the graph.
QueryResult
Query result object containing rows and columns.
Properties
columns: list[str]- List of column names
Methods
__len__() -> int- Number of rows__getitem__(index: int) -> dict- Get row by index__iter__()- Iterate over rowsto_list() -> list[dict]- Convert all rows to a list of dictionaries
Example
result = g.execute("MATCH (n) RETURN n, n.name LIMIT 5")
print(f"Columns: {result.columns}") # ['n', 'n.name']
print(f"Rows: {len(result)}") # 5
# Access by index
first_row = result[0]
print(first_row['n.name'])
# Iterate
for row in result:
print(row['n.name'])
# Convert to list
all_data = result.to_list()
Supported Data Types
Python types are automatically converted to/from Cypher types:
| Python Type | Cypher Type | Notes |
|---|---|---|
None |
NULL |
- |
bool |
BOOLEAN |
- |
int |
INTEGER |
- |
float |
FLOAT |
- |
str |
STRING |
- |
list |
LIST |
Nested lists supported |
dict |
MAP |
- |
Graph types (Node, Relationship, Path) are returned as dictionaries with a _type field:
result = g.execute("MATCH (n:Person {name: 'Alice'}) RETURN n")
node = result[0]['n']
print(node['_type']) # 'Node'
print(node['id']) # Node ID
print(node['labels']) # ['Person']
print(node['properties']) # {'name': 'Alice', 'age': 30}
Advanced Examples
Parameterized Queries
# Create with parameters
g.execute(
"CREATE (p:Person {name: $name, age: $age})",
{"name": "Charlie", "age": 35}
)
# Query with parameters
result = g.execute(
"MATCH (p:Person) WHERE p.age BETWEEN $min AND $max RETURN p",
{"min": 25, "max": 35}
)
Working with Relationships
# Create relationship with properties
g.execute("""
MATCH (a:Person {name: 'Alice'})
MATCH (b:Person {name: 'Bob'})
CREATE (a)-[:KNOWS {since: 2020, strength: 0.8}]->(b)
""")
# Query relationships
result = g.execute("""
MATCH (a:Person)-[r:KNOWS]->(b:Person)
RETURN a.name, r.since, r.strength, b.name
""")
for row in result:
print(f"{row['a.name']} knows {row['b.name']} since {row['r.since']}")
Aggregations
result = g.execute("""
MATCH (p:Person)
RETURN
count(p) as total,
avg(p.age) as avg_age,
min(p.age) as min_age,
max(p.age) as max_age
""")
stats = result[0]
print(f"Total: {stats['total']}, Avg Age: {stats['avg_age']:.1f}")
Path Queries
# Find shortest path
result = g.execute("""
MATCH path = shortestPath(
(a:Person {name: 'Alice'})-[:KNOWS*]-(b:Person {name: 'Charlie'})
)
RETURN path
""")
path = result[0]['path']
print(f"Path length: {len(path['nodes']) - 1}")
Performance Tips
- Use parameters instead of string formatting for better performance and security
- Batch operations when creating many nodes/relationships
- Use LIMIT for large result sets
- Create indexes for frequently queried properties (when index support is added)
Development
Building from source:
# Install maturin
pip install maturin
# Build and install in development mode
cd python-bindings
maturin develop
# Build release wheel
maturin build --release
# Run tests
python -m pytest
License
Apache 2.0 - See LICENSE for details.
Links
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ocpg-0.2.0.tar.gz.
File metadata
- Download URL: ocpg-0.2.0.tar.gz
- Upload date:
- Size: 13.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ebc7e5b9ee5a0dd84db3a747aa52024c8d5ff0ea8a7032bff0120272c7041d5d
|
|
| MD5 |
6b8fbe75eee7a726dc04c06c47644894
|
|
| BLAKE2b-256 |
5ad11884bb131eeff365db6a0b0e79d3724189b46ef426345948ba286b545eed
|
File details
Details for the file ocpg-0.2.0-cp38-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: ocpg-0.2.0-cp38-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.6 MB
- Tags: CPython 3.8+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d8eb412e9020a8489711789ae1197c04f67faeb1e0c8563855c0955e9b6aa28f
|
|
| MD5 |
748ab6fb5fe5acfa61bef900088563b6
|
|
| BLAKE2b-256 |
4c52ff02b40b64563cc00c10ce6e6dafcfdea3704044d8bd6676640aded23581
|