1概览
本 notebook 介绍 Semantica 中的 Amazon Neptune 数据库集成。Amazon Neptune 是一个全托管的图数据库服务,同时支持属性图(通过 OpenCypher/Gremlin)和 RDF 图(通过 SPARQL)。
关键特性
- IAM 认证:通过 AuthManager 使用 AWS SigV4 签名进行安全访问
- OpenCypher 支持:使用标准 OpenCypher 语法进行查询
- Bolt 协议:使用 Neo4j Bolt 驱动进行高效的二进制通信
- 原生 ~id 支持:利用 Neptune 的原生元素 ID 处理
- 完整 CRUD 操作:创建、读取、更新、删除节点和关系
- 自动重试:内置针对瞬时错误带指数退避的重试逻辑
前置条件
- 一个 Amazon Neptune 数据库集群
- 已配置的 AWS 凭证(boto3、环境变量或 IAM 角色)
- 到你的 Neptune 集群的网络访问(VPC、安全组)
- 你的公网 IP 地址或 VPN/办公室 CIDR(运行
curl ifconfig.me查找你的公网 IP),用于下文限制数据库访问
使用 CloudFormation 快速设置
如果你没有 Neptune 集群,使用提供的 CloudFormation 模板创建一个带公网端点和 IAM 认证的集群:
# 部署 Neptune 栈(大约需要 15-20 分钟)
# 将 203.0.113.25/32 替换为你自己的公网 IP(运行 `curl ifconfig.me` 查找)
# 或你的办公室/VPN CIDR。这会在网络层面限制谁能访问数据库——
# 除了短期的本地实验外,绝不要将其放宽到 0.0.0.0/0。
aws cloudformation create-stack \
--stack-name semantica-neptune \
--template-body file://neptune-setup.yaml \
--parameters ParameterKey=ClientCidr,ParameterValue=203.0.113.25/32 \
--capabilities CAPABILITY_NAMED_IAM
# 等待栈创建完成
aws cloudformation wait stack-create-complete --stack-name semantica-neptune
# 获取输出(端点、端口、凭证)
aws cloudformation describe-stacks --stack-name semantica-neptune \
--query 'Stacks[0].Outputs' --output table
该模板会创建:
- 带公网子网、互联网网关和 VPC 流日志(到 CloudWatch Logs)的 VPC
- 启用了 IAM 认证的 Neptune 集群(db.t3.medium)
- 具有用于 OpenCypher 查询的最小权限访问的 IAM 用户
- 仅允许来自你指定的 ClientCidr 访问 Bolt 协议(端口 8182)的安全组
⚠️ 安全说明:为简化演示/测试环境,此模板创建了一个带静态访问密钥的 IAM 用户。对于生产环境,我们推荐使用 IAM 角色(EC2 实例角色、ECS 任务角色、Lambda 执行角色),它们提供会自动轮换的临时凭证。CloudFormation 输出中的秘密访问密钥以明文提供,以简化初始设置——在生产环境中,请使用 AWS Secrets Manager。
ClientCidr参数是必需的(无默认值),正是为了确保数据库绝不会被静默地暴露给整个互联网。
输出:
- NeptuneEndpoint - 集群主机名(用作 NEPTUNE_ENDPOINT)
- NeptunePort - 8182(用作 NEPTUNE_PORT)
- AwsAccessKeyId - IAM 用户访问密钥(用作 AWS_ACCESS_KEY_ID)
- AwsSecretAccessKey - IAM 用户秘密密钥,明文(用作 AWS_SECRET_ACCESS_KEY)
- AwsRegion - 部署区域(用作 AWS_REGION)
清理:
# 删除 CloudFormation 栈
aws cloudformation delete-stack --stack-name semantica-neptune
预估月度成本(在 100% 利用率下约为每月 100-105 美元):
| 资源 | 成本(美元) |
|---|---|
| Neptune db.t3.medium 实例 | 约 96/月(0.132/小时) |
| 存储(10 GB) | 约 1/月 |
| I/O 请求 | 约 1-5/月 |
| 公网 IPv4 地址 | 约 3.60/月(0.005/小时) |
| VPC 流日志(CloudWatch Logs) | 约 1-2/月,取决于流量 |
| VPC、子网、路由表、互联网网关、IAM | 无额外费用 |
免费套餐:新的 Neptune 用户可免费使用 30 天(750 小时 db.t3.medium、1000 万次 I/O、1 GB 存储)。不使用时删除该栈以避免产生费用。
2安装
# 安装带 Neptune 支持的 Semantica
pip install semantica
# 所需依赖(自动安装)
pip install boto3 neo4j
# 安装 semantica 包
!pip install semantica
3配置
设置你的 Neptune 集群端点和 AWS 凭证。将占位值替换为你的实际配置。
import os
# Neptune 集群配置 - 替换为你的值
# (从 CloudFormation 栈输出中获取这些值)
os.environ["NEPTUNE_ENDPOINT"] = "your-cluster.us-east-1.neptune.amazonaws.com"
os.environ["NEPTUNE_PORT"] = "8182"
os.environ["AWS_REGION"] = "us-east-1"
# 用于 IAM 认证的 AWS 凭证
# 选项 1:IAM 用户(来自 CloudFormation 模板的静态凭证)
# os.environ["AWS_ACCESS_KEY_ID"] = "AKIA..." # 来自 AwsAccessKeyId 输出
# os.environ["AWS_SECRET_ACCESS_KEY"] = "..." # 来自 AwsSecretAccessKey 输出
# 注意:IAM 用户不需要 AWS_SESSION_TOKEN
# 选项 2:IAM 角色 / 临时凭证(例如 STS AssumeRole、EC2 实例角色)
# os.environ["AWS_ACCESS_KEY_ID"] = "ASIA..." # 临时访问密钥
# os.environ["AWS_SECRET_ACCESS_KEY"] = "..." # 临时秘密密钥
# os.environ["AWS_SESSION_TOKEN"] = "..." # 临时凭证必需
print(f"Neptune Endpoint: {os.environ.get('NEPTUNE_ENDPOINT')}")
print(f"AWS Region: {os.environ.get('AWS_REGION')}")
4步骤 1:初始化 Neptune 存储
使用 IAM 认证初始化到你的 Amazon Neptune 集群的连接。
import os
from semantica.graph_store import GraphStore
# 选项 1:使用 GraphStore 工厂(推荐)
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,
)
# 连接到 Neptune
neptune_store.connect()
print("Connected to Amazon Neptune!")
无需 IAM 认证的开发/测试
对于不需要 IAM 认证的开发或测试环境(例如 Neptune notebook 或仅 VPC 访问),你可以禁用 IAM 签名:
# 用于无 IAM 认证的开发/测试环境
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, # 为开发/测试禁用 IAM 签名
)
neptune_store_dev.connect()
认证选项
IAM 认证(生产环境推荐)自动使用 AWS 凭证链: 1. 环境变量(AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY) 2. AWS 凭证文件(~/.aws/credentials) 3. IAM 角色(用于 EC2、Lambda、ECS)
5步骤 2:节点操作
创建节点
节点代表图中的实体。每个节点可以有:
- ID:唯一标识符(自定义或自动生成的 UUID)
- 标签:类别/类型(例如 Person、Company)
- 属性:键值对(例如 {"name": "Alice", "age": 30})
# 使用自定义 ID 创建单个节点(id 在属性中)
alice = neptune_store.create_node(
labels=["Person"],
properties={"id": "alice", "name": "Alice", "age": 30, "role": "Engineer"}
)
print(f"Created node: {alice}")
# 使用自动生成的 UUID 创建节点(属性中无 id)
bob = neptune_store.create_node(
labels=["Person"],
properties={"name": "Bob", "age": 25, "role": "Designer"}
)
print(f"Created node with UUID: {bob['id']}")
# 使用自动生成的 ID 创建公司节点
acme = neptune_store.create_node(
labels=["Company"],
properties={"name": "Acme Corp", "industry": "Technology", "founded": 2010}
)
print(f"Created company: {acme}")
批量创建多个节点
# 批量创建节点以获得更好的性能
# 在属性中包含 'id' 以使用自定义 ID
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")
检索节点
# 按 ID 获取特定节点
alice_node = neptune_store.get_node(node_id="alice")
print(f"Retrieved: {alice_node}")
# 按标签获取节点
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')}")
# 按属性获取节点
engineers = neptune_store.get_nodes(
labels=["Person"],
properties={"role": "Engineer"},
limit=5
)
print(f"Found {len(engineers)} engineers")
更新节点
# 更新节点属性(合并模式 - 默认)
updated_alice = neptune_store.update_node(
node_id="alice",
properties={"age": 31, "department": "AI Research"},
merge=True
)
print(f"Updated Alice: {updated_alice}")
# 替换所有属性(merge=False)
# 警告:这会移除不在更新中的属性
replaced = neptune_store.update_node(
node_id="charlie",
properties={"name": "Charlie", "age": 36},
merge=False
)
删除节点
# 删除节点(使用 detach=True 同时删除关系)
deleted = neptune_store.delete_node(node_id="diana", detach=True)
print(f"Deleted diana: {deleted}")
# 不使用 detach(如果节点有关系则会失败)
# neptune_store.delete_node(node_id="alice", detach=False)
6步骤 3:关系操作
创建关系
关系连接节点,表示实体之间的连接。
# 在 Alice 和 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}")
# 在人与人之间创建 KNOWS 关系
knows_rel = neptune_store.create_relationship(
start_node_id="alice",
end_node_id=bob["id"],
rel_type="KNOWS",
properties={"since": 2019}
)
检索关系
# 获取某个节点的所有关系
alice_rels = neptune_store.get_relationships(node_id="alice", direction="both")
print(f"Alice has {len(alice_rels)} relationships")
# 仅获取出向关系
outgoing = neptune_store.get_relationships(node_id="alice", direction="out")
# 按关系类型过滤
works_rels = neptune_store.get_relationships(
node_id="alice",
rel_type="WORKS_AT",
direction="out"
)
print(f"Alice's work relationships: {len(works_rels)}")
删除关系
# 按 ID 删除特定关系
if works_at.get("id"):
deleted = neptune_store.delete_relationship(rel_id=works_at["id"])
print(f"Deleted relationship: {deleted}")
7步骤 4:OpenCypher 查询
Amazon Neptune 通过 Bolt 协议支持 OpenCypher 查询。使用标准 Cypher 语法执行复杂的图模式。
# 简单查询
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")
# 使用参数(更安全、更高效)
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', []))}")
# 查找节点之间的关系
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']}")
# 计数和聚合
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}")
8步骤 5:图分析
获取邻居
遍历图以查找相连的节点。
# 获取直接邻居(depth=1)
neighbors = neptune_store.get_neighbors(
node_id="alice",
direction="both",
depth=1
)
print(f"Alice's direct neighbors: {len(neighbors)}")
# 获取最多 2 跳之外的邻居
extended = neptune_store.get_neighbors(
node_id="alice",
direction="out",
depth=2
)
print(f"Nodes within 2 hops: {len(extended)}")
最短路径
查找两个节点之间的最短路径。
# 查找最短路径
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")
9步骤 6:图统计
获取关于你的图的全面统计信息。
# 获取图统计信息
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}")
10步骤 7:连接管理
完成后始终关闭连接以释放资源。
# 检查连接状态
status = neptune_store.get_status()
print(f"Connection status: {status}")
# 关闭连接
neptune_store.close()
print("Connection closed")
11Neptune 特有注意事项
原生元素 ID
Neptune 使用原生 ~id 进行元素标识。在属性中包含 id 以设置自定义 ID:
# 使用自定义 ID 创建节点(在属性中包含 'id')
node = neptune_store.create_node(
labels=["Person"],
properties={"id": "my-custom-id", "name": "Test"}
)
# 使用自动生成的 UUID 创建节点(从属性中省略 'id')
node = neptune_store.create_node(
labels=["Person"],
properties={"name": "Test"}
)
# 该 ID 在内部用于 id() 函数调用:
# MATCH (n) WHERE id(n) = 'my-custom-id' RETURN n
OpenCypher 注意事项
Amazon Neptune 数据库的 OpenCypher 实现与 Neo4j 有一些差异:
- 没有
shortestPath()函数:使用变长路径模式或allShortestPaths() - 标签语法:使用
labels(n)函数检索节点标签 - 属性更新:使用
SET n += {props}实现合并行为
有关 Amazon Neptune 数据库支持的完整 OpenCypher 规范,请参阅 AWS 文档。
Amazon Neptune Analytics
对于分析型(OLAP)工作负载,如图算法、聚合和大规模遍历,请考虑使用 Amazon Neptune Analytics。Neptune Analytics 通过为分析查询提供优化性能来补充 Neptune 数据库,而 Neptune 数据库则针对事务型(OLTP)工作负载进行了优化。
性能提示
- 使用批量操作来创建多个节点/关系
- 在查询中使用参数以启用查询缓存
- 使用
LIMIT子句限制结果集
12小结
本 notebook 介绍了 Amazon Neptune 图存储集成:
- IAM 认证:安全的 AWS SigV4 签名
- CRUD 操作:完整的节点和关系管理
- OpenCypher 查询:标准图查询语言
- 图分析:邻居和最短路径算法
- 统计与监控:图指标和状态
关键要点
- Neptune 使用原生
~id进行元素标识 - 生产环境推荐使用 IAM 认证
- Bolt 协议提供高效的二进制查询接口
- Semantica 抽象了 Neptune 特有的语法差异
下一步
- 图存储(Neo4j/FalkorDB) - 与其他后端比较
- 构建知识图谱 - 构建生产级知识图谱
- 图分析 - 高级分析算法