mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-08-29 04:26:20 +00:00
Includes the CloudFormation template in the same directory as the [Amazon Neptune Cookbook](https://github.com/Hawksight-AI/semantica/blob/main/cookbook/introduction/21_Amazon_Neptune_Store.ipynb) and references it as a prerequisite in the cookbook.
23 KiB
23 KiB
In [ ]:
!pip install semanticaIn [ ]:
import os
# Neptune cluster configuration - REPLACE WITH YOUR VALUES
# (Get these from CloudFormation stack outputs)
os.environ["NEPTUNE_ENDPOINT"] = "your-cluster.us-east-1.neptune.amazonaws.com"
os.environ["NEPTUNE_PORT"] = "8182"
os.environ["AWS_REGION"] = "us-east-1"
# AWS credentials for IAM Authentication
# Option 1: IAM User (static credentials from CloudFormation template)
# os.environ["AWS_ACCESS_KEY_ID"] = "AKIA..." # From AwsAccessKeyId output
# os.environ["AWS_SECRET_ACCESS_KEY"] = "..." # From AwsSecretAccessKey output
# Note: No AWS_SESSION_TOKEN needed for IAM users
# Option 2: IAM Role / Temporary credentials (e.g., STS AssumeRole, EC2 instance role)
# os.environ["AWS_ACCESS_KEY_ID"] = "ASIA..." # Temporary access key
# os.environ["AWS_SECRET_ACCESS_KEY"] = "..." # Temporary secret key
# os.environ["AWS_SESSION_TOKEN"] = "..." # REQUIRED for temporary credentials
print(f"Neptune Endpoint: {os.environ.get('NEPTUNE_ENDPOINT')}")
print(f"AWS Region: {os.environ.get('AWS_REGION')}")In [ ]:
import os
from semantica.graph_store import GraphStore
# Option 1: Using GraphStore factory (recommended)
neptune_store = GraphStore(
backend="neptune",
endpoint=os.environ.get("NEPTUNE_ENDPOINT"),
port=int(os.environ.get("NEPTUNE_PORT", 8182)),
region=os.environ.get("AWS_REGION", "us-east-1"),
iam_auth=True,
)
# Connect to Neptune
neptune_store.connect()
print("Connected to Amazon Neptune!")In [ ]:
# For dev/test environments without IAM authentication
neptune_store_dev = GraphStore(
backend="neptune",
endpoint=os.environ.get("NEPTUNE_ENDPOINT"),
port=int(os.environ.get("NEPTUNE_PORT", 8182)),
region=os.environ.get("AWS_REGION", "us-east-1"),
iam_auth=False, # Disable IAM signing for dev/test
)
neptune_store_dev.connect()In [ ]:
# Create a single node with custom ID (id in properties)
alice = neptune_store.create_node(
labels=["Person"],
properties={"id": "alice", "name": "Alice", "age": 30, "role": "Engineer"}
)
print(f"Created node: {alice}")
# Create a node with auto-generated UUID (no id in properties)
bob = neptune_store.create_node(
labels=["Person"],
properties={"name": "Bob", "age": 25, "role": "Designer"}
)
print(f"Created node with UUID: {bob['id']}")
# Create a company node with auto-generated ID
acme = neptune_store.create_node(
labels=["Company"],
properties={"name": "Acme Corp", "industry": "Technology", "founded": 2010}
)
print(f"Created company: {acme}")In [ ]:
# Batch create nodes for better performance
# Include 'id' in properties for custom IDs
nodes_data = [
{"labels": ["Person"], "properties": {"id": "charlie", "name": "Charlie", "age": 35}},
{"labels": ["Person"], "properties": {"id": "diana", "name": "Diana", "age": 28}},
{"labels": ["Location"], "properties": {"name": "San Francisco", "state": "CA"}},
]
created_nodes = neptune_store.create_nodes(nodes_data)
print(f"Created {len(created_nodes)} nodes in batch")In [ ]:
# Get a specific node by ID
alice_node = neptune_store.get_node(node_id="alice")
print(f"Retrieved: {alice_node}")
# Get nodes by label
people = neptune_store.get_nodes(labels=["Person"], limit=10)
print(f"Found {len(people)} Person nodes:")
for person in people:
print(f" - {person.get('properties', {}).get('name')}")
# Get nodes by properties
engineers = neptune_store.get_nodes(
labels=["Person"],
properties={"role": "Engineer"},
limit=5
)
print(f"Found {len(engineers)} engineers")In [ ]:
# Update node properties (merge mode - default)
updated_alice = neptune_store.update_node(
node_id="alice",
properties={"age": 31, "department": "AI Research"},
merge=True
)
print(f"Updated Alice: {updated_alice}")
# Replace all properties (merge=False)
# WARNING: This removes properties not in the update
replaced = neptune_store.update_node(
node_id="charlie",
properties={"name": "Charlie", "age": 36},
merge=False
)In [ ]:
# Delete a node (with detach=True to also delete relationships)
deleted = neptune_store.delete_node(node_id="diana", detach=True)
print(f"Deleted diana: {deleted}")
# Without detach (fails if node has relationships)
# neptune_store.delete_node(node_id="alice", detach=False)In [ ]:
# Create a relationship between Alice and Acme
works_at = neptune_store.create_relationship(
start_node_id="alice",
end_node_id=acme["id"],
rel_type="WORKS_AT",
properties={"since": 2020, "position": "Senior Engineer"}
)
print(f"Created relationship: {works_at}")
# Create a KNOWS relationship between people
knows_rel = neptune_store.create_relationship(
start_node_id="alice",
end_node_id=bob["id"],
rel_type="KNOWS",
properties={"since": 2019}
)In [ ]:
# Get all relationships for a node
alice_rels = neptune_store.get_relationships(node_id="alice", direction="both")
print(f"Alice has {len(alice_rels)} relationships")
# Get outgoing relationships only
outgoing = neptune_store.get_relationships(node_id="alice", direction="out")
# Filter by relationship type
works_rels = neptune_store.get_relationships(
node_id="alice",
rel_type="WORKS_AT",
direction="out"
)
print(f"Alice's work relationships: {len(works_rels)}")In [ ]:
# Delete a specific relationship by ID
if works_at.get("id"):
deleted = neptune_store.delete_relationship(rel_id=works_at["id"])
print(f"Deleted relationship: {deleted}")In [ ]:
# Simple query
results = neptune_store.execute_query(
"MATCH (p:Person) RETURN p.name, p.age ORDER BY p.age"
)
print("People in the graph:")
for record in results.get("records", []):
print(f" - {record.get('p.name')}: {record.get('p.age')} years old")In [ ]:
# Using parameters (safer and more efficient)
results = neptune_store.execute_query(
"MATCH (p:Person) WHERE p.age > $min_age RETURN p.name, p.age",
parameters={"min_age": 25}
)
print(f"People over 25: {len(results.get('records', []))}")In [ ]:
# Find relationships between nodes
results = neptune_store.execute_query("""
MATCH (p:Person)-[r:WORKS_AT]->(c:Company)
RETURN p.name as employee, c.name as company, r.since as start_year
""")
for record in results.get("records", []):
print(f"{record['employee']} works at {record['company']} since {record['start_year']}")In [ ]:
# Count and aggregate
results = neptune_store.execute_query("""
MATCH (p:Person)
RETURN count(p) as total, avg(p.age) as avg_age, max(p.age) as max_age
""")
stats = results.get("records", [{}])[0]
print(f"Total: {stats.get('total')}, Avg Age: {stats.get('avg_age'):.1f}")In [ ]:
# Get immediate neighbors (depth=1)
neighbors = neptune_store.get_neighbors(
node_id="alice",
direction="both",
depth=1
)
print(f"Alice's direct neighbors: {len(neighbors)}")
# Get neighbors up to 2 hops away
extended = neptune_store.get_neighbors(
node_id="alice",
direction="out",
depth=2
)
print(f"Nodes within 2 hops: {len(extended)}")In [ ]:
# Find shortest path
path = neptune_store.shortest_path(
start_node_id="alice",
end_node_id="charlie",
max_depth=5
)
if path:
print("Path found!")
print(f" Length: {path.get('length')}")
print(f" Nodes: {len(path.get('nodes', []))}")
print(f" Relationships: {len(path.get('relationships', []))}")
else:
print("No path found between nodes")In [ ]:
# Get graph statistics
stats = neptune_store.get_stats()
print("Graph Statistics:")
print(f" Total nodes: {stats.get('node_count', 'N/A')}")
print(f" Total relationships: {stats.get('relationship_count', 'N/A')}")
print("\nNode labels:")
for label, count in stats.get('label_counts', {}).items():
print(f" - {label}: {count}")
print("\nRelationship types:")
for rel_type, count in stats.get('relationship_type_counts', {}).items():
print(f" - {rel_type}: {count}")In [ ]:
# Check connection status
status = neptune_store.get_status()
print(f"Connection status: {status}")
# Close the connection
neptune_store.close()
print("Connection closed")