数据类型及其到 Cypher 类型的映射
本节中的表格显示了 Cypher 数据类型与 Python 类型之间的映射。
核心类型
Cypher 类型 | Python 类型 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
完整文档请参见API 文档 — 核心数据类型。
时间类型
时间数据类型由 neo4j.time
模块实现。它提供了一组符合 ISO-8601 和 Cypher 的类型,这些类型与 Python 原生 datetime
模块中的类型相似。要在驱动程序类型和原生类型之间进行转换,请使用 .from_native()
和 .to_native()
方法(不适用于 Duration
)。此转换会造成精度损失,因为驱动程序的类型支持纳秒精度,而 Python 的原生类型不支持。
驱动程序的时间类型旨在与 pytz 一起使用。其他 datetime.tzinfo 实现(例如 datetime.timezone 、zoneinfo 、dateutil.tz )不受支持,并且可能无法正常工作。 |
有关时区缩写的列表,请参见tz 数据库时区列表。
Cypher 类型 | Python 类型 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
† tzinfo
不为 None
的情况。
†† tzinfo
为 None
的情况。
from datetime import datetime
import pytz
from neo4j import GraphDatabase
from neo4j.time import DateTime
URI = "{neo4j-database-uri}"
AUTH = ("{neo4j-username}", "{neo4j-password}")
friends_since = DateTime(year=1999, month=11, day=23,
hour=7, minute=47, nanosecond=4123)
friends_since = pytz.timezone("US/Eastern").localize(friends_since)
# Python's native datetimes work as well.
# They don't support the full feature-set of Neo4j's type though.
# py_friends_since = datetime(year=1999, month=11, day=23, hour=7, minute=47)
# py_friends_since = pytz.timezone("US/Eastern").localize(py_friends_since)
# Create a friendship with the given DateTime, and return the DateTime
with GraphDatabase.driver(URI, auth=AUTH) as driver:
records, summary, keys = driver.execute_query("""
MERGE (a:Person {name: $name})
MERGE (b:Person {name: $friend})
MERGE (a)-[friendship:KNOWS {since: $friends_since}]->(b)
RETURN friendship.since
""", name="Alice", friend="Bob",
friends_since=friends_since # or friends_since=py_friends_since
)
out_datetime = records[0]["friendship.since"]
print(out_datetime) # 1999-11-23T07:47:00.000004123-05:00
# Converting DateTime to native datetime (lossy)
py_out_datetime = out_datetime.to_native() # type: datetime
print(py_out_datetime) # 1999-11-23 07:47:00.000004-05:00
完整文档请参见API 文档 — 时间数据类型。
日期
表示一个只捕获日期,不捕获时间或时区的时刻。
from neo4j.time import Date
d = Date(year=2021, month=11, day=2)
print(d) # '2021-11-02'
完整文档请参见API 文档 — 时间数据类型 — 日期。
时间
表示一个捕获时间(以秒为单位的时区偏移量)但不捕获日期的时刻。
from neo4j.time import Time
import pytz
t = Time(hour=7, minute=47, nanosecond=4123, tzinfo=pytz.FixedOffset(-240))
print(t) # '07:47:00.000004123-04:00'
完整文档请参见API 文档 — 时间数据类型 — 时间。
本地时间
表示一个只捕获一天中的时间,不捕获日期或时区的时刻。
from neo4j.time import Time
t = Time(hour=7, minute=47, nanosecond=4123)
print(t) # '07:47:00.000004123'
完整文档请参见API 文档 — 时间数据类型 — 时间。
日期时间
表示一个捕获日期、时间及有时区标识符的时刻。
from neo4j.time import DateTime
import pytz
dt = DateTime(year=2021, month=11, day=2, hour=7, minute=47, nanosecond=4123)
dt = pytz.timezone("US/Eastern").localize(dt) # time zone localization (optional)
print(dt) # '2021-11-02T07:47:00.000004123-04:00'
完整文档请参见API 文档 — 时间数据类型 — 日期时间。
本地日期时间
表示一个捕获日期和时间,但不捕获时区的时刻。
from neo4j.time import DateTime
dt = DateTime(year=2021, month=11, day=2, hour=7, minute=47, nanosecond=4123)
print(dt) # '2021-11-02T07:47:00.000004123'
完整文档请参见API 文档 — 时间数据类型 — 日期时间。
持续时间
表示两个时间点之间的差值。作为参数传入的 datetime.timedelta
对象将始终隐式转换为 neo4j.time.Duration
。无法从 neo4j.time.Duration
转换为 datetime.timedelta
(因为 datetime.timedelta
缺少对月份的支持)。
from neo4j.time import Duration
duration = Duration(years=1, days=2, seconds=3, nanoseconds=4)
print(duration) # 'P1Y2DT3.000000004S'
完整文档请参见API 文档 — 时间数据类型 — 持续时间。
空间类型
Cypher 支持空间值(点),Neo4j 可以将这些点值作为节点和关系的属性存储。
对象属性 srid
(空间参考标识符的缩写)是一个数字,用于标识空间类型应被解释的坐标系。您可以将其视为每种空间类型的唯一标识符。
Cypher 类型 | Python 类型 |
---|---|
|
|
|
|
|
|
完整文档请参见API 文档 — 空间类型。
CartesianPoint
表示 2D/3D 笛卡尔空间中的一个点。
公开属性 x
、y
、z
(z
仅适用于 3D 点)。
from neo4j.spatial import CartesianPoint
# A 2D CartesianPoint
point = CartesianPoint((1.23, 4.56))
print(point.x, point.y, point.srid)
# 1.23 4.56 7203
# A 3D CartesianPoint
point = CartesianPoint((1.23, 4.56, 7.89))
print(point.x, point.y, point.z, point.srid)
# 1.23 4.56 7.8 9157
完整文档请参见API 文档 — 空间类型 — CartesianPoint。
WGS84Point
表示全球大地测量系统 (WGS84) 中的一个点。
公开属性 longitude
、latitude
、height
(height
仅适用于 3D 点),它们是 x
、y
、z
的别名。
from neo4j.spatial import WGS84Point
# A 2D WGS84Point
point = WGS84Point((1.23, 4.56))
print(point.longitude, point.latitude, point.srid)
# or print(point.x, point.y, point.srid)
# 1.23 4.56 4326
# A 3D WGS84Point
point = WGS84Point((1.23, 4.56, 7.89))
print(point.longitude, point.latitude, point.height, point.srid)
# or print(point.x, point.y, point.z, point.srid)
# 1.23 4.56 7.89 4979
完整文档请参见API 文档 — 空间类型 — WSG84Point。
图类型
图类型仅作为结果传递,不能用作参数。部分 操作查询结果 — 转换为图 包含了使用图类型的示例。
Cypher 类型 | Python 类型 |
---|---|
|
|
|
|
|
|
完整文档请参见API 文档 — 图类型。
节点
表示图中的一个节点。
属性 element_id
提供实体的标识符。应谨慎使用此属性,因为无法保证 id 值与单个事务范围之外的元素之间的映射。换句话说,在不同事务中使用 element_id
来 MATCH
元素是危险的。
from neo4j import GraphDatabase
URI = "{neo4j-database-uri}"
AUTH = ("{neo4j-username}", "{neo4j-password}")
with GraphDatabase.driver(URI, auth=AUTH) as driver:
records, _, _ = driver.execute_query(
"MERGE (p:Person {name: $name}) RETURN p AS person",
name="Alice",
database_="neo4j",
)
for record in records:
node = record["person"]
print(f"Node ID: {node.element_id}\n"
f"Labels: {node.labels}\n"
f"Properties: {node.items()}\n"
)
# Node ID: 4:73e9a61b-b501-476d-ad6f-8d7edf459251:0
# Labels: frozenset({'Person'})
# Properties: dict_items([('name', 'Alice')])
完整文档请参见API 文档 — 图类型 — 节点。
关系
表示图中的一个关系。
属性 element_id
提供实体的标识符。应谨慎使用此属性,因为无法保证 id 值与单个事务范围之外的元素之间的映射。
from neo4j import GraphDatabase
URI = "{neo4j-database-uri}"
AUTH = ("{neo4j-username}", "{neo4j-password}")
with GraphDatabase.driver(URI, auth=AUTH) as driver:
records, _, _ = driver.execute_query("""
MERGE (p:Person {name: $name})
MERGE (p)-[r:KNOWS {status: $status, since: date()}]->(friend:Person {name: $friend_name})
RETURN r AS friendship
""", name="Alice", status="BFF", friend_name="Bob",
)
for record in records:
relationship = record["friendship"]
print(f"Relationship ID: {relationship.element_id}\n"
f"Start node: {relationship.start_node}\n"
f"End node: {relationship.end_node}\n"
f"Type: {relationship.type}\n"
f"Friends since: {relationship.get('since')}\n"
f"All properties: {relationship.items()}\n"
)
# Relationship ID: 5:73e9a61b-b501-476d-ad6f-8d7edf459251:1
# Start node: <Node element_id='4:73e9a61b-b501-476d-ad6f-8d7edf459251:0' labels=frozenset({'Person'}) properties={'name': 'Alice'}>
# End node: <Node element_id='4:73e9a61b-b501-476d-ad6f-8d7edf459251:2' labels=frozenset({'Person'}) properties={'name': 'Bob'}>
# Type: KNOWS
# Friends since: 2022-11-07
# All properties: dict_items([('since', neo4j.time.Date(2022, 11, 7)), ('status', 'BFF')])
完整文档请参见API 文档 — 图类型 — 关系。
路径
表示图中的一条路径。
from neo4j import GraphDatabase
from neo4j.time import Date
URI = "{neo4j-database-uri}"
AUTH = ("{neo4j-username}", "{neo4j-password}")
def add_friend(driver, name, status, date, friend_name):
driver.execute_query("""
MERGE (p:Person {name: $name})
MERGE (p)-[r:KNOWS {status: $status, since: $date}]->(friend:Person {name: $friend_name})
""", name=name, status=status, date=date, friend_name=friend_name,
database_="neo4j",
)
with GraphDatabase.driver(URI, auth=AUTH) as driver:
# Create some :Person nodes linked by :KNOWS relationships
add_friend(driver, name="Alice", status="BFF", date=Date.today(), friend_name="Bob")
add_friend(driver, name="Bob", status="Fiends", date=Date.today(), friend_name="Sofia")
add_friend(driver, name="Sofia", status="Acquaintances", date=Date.today(), friend_name="Sofia")
# Follow :KNOWS relationships outgoing from Alice three times, return as path
records, _, _ = driver.execute_query("""
MATCH path=(:Person {name: $name})-[:KNOWS*3]->(:Person)
RETURN path AS friendship_chain
""", name="Alice",
database_="neo4j",
)
path = records[0]["friendship_chain"]
print("-- Path breakdown --")
for friendship in path:
print("{name} is friends with {friend} ({status})".format(
name=friendship.start_node.get("name"),
friend=friendship.end_node.get("name"),
status=friendship.get("status"),
))
完整文档请参见API 文档 — 图类型 — 路径。
扩展类型
驱动程序支持更多类型作为查询参数,它们会自动映射到核心类型之一。由于这种转换,并且因为服务器不了解这些扩展类型,驱动程序永远不会在结果中返回这些类型,而总是返回它们对应的映射。
参数类型 | 映射的 Python 类型 |
---|---|
tuple |
|
bytearray |
|
numpy |
|
pandas |
|
pandas |
|
pandas |
|
通常,如果您不确定给定参数将发生的类型转换,可以按照以下示例进行测试
import neo4j
with neo4j.GraphDatabase.driver(URI, auth=AUTH) as driver:
type_in = ("foo", "bar")
records, _, _ = driver.execute_query("RETURN $x AS type_out", x=type_in)
type_out = records[0].get("type_out")
print(type(type_out)) # <class 'list'>
print(type_out) # ['foo', 'bar']
异常
某些服务器错误被标记为可以安全重试,无需更改原始请求。此类错误的示例包括死锁、内存问题或连接问题。所有驱动程序的异常类型都实现了 .is_retryable()
方法,该方法提供了关于进一步尝试是否可能成功的见解。这在显式事务中运行查询时特别有用,可以判断失败的查询是否值得重新运行。
词汇表
- LTS
-
长期支持版本是保证支持多年的版本。Neo4j 4.4 是 LTS 版本,Neo4j 5 也将有一个 LTS 版本。
- Aura
-
Aura 是 Neo4j 的全托管云服务。它提供免费和付费计划。
- Cypher
-
Cypher 是 Neo4j 的图查询语言,允许您从数据库中检索数据。它类似于 SQL,但适用于图。
- APOC
-
Awesome Procedures On Cypher (APOC) 是一个(包含许多)无法在 Cypher 本身轻松表达的函数库。
- Bolt
-
Bolt 是 Neo4j 实例与驱动程序之间交互所使用的协议。它默认监听端口 7687。
- ACID
-
原子性、一致性、隔离性、持久性 (ACID) 是保证数据库事务可靠处理的属性。符合 ACID 的 DBMS 确保数据库中的数据即使在发生故障时也能保持准确和一致。
- 最终一致性
-
如果数据库提供所有集群成员将在某个时间点存储最新版本数据的保证,则该数据库是最终一致的。
- 因果一致性
-
如果集群的每个成员都以相同的顺序看到读写查询,则数据库是因果一致的。这比最终一致性更强。
- NULL
-
空标记不是一种类型,而是表示值缺失的占位符。更多信息请参见Cypher → 使用
null
。 - 事务
-
事务是一个工作单元,它要么整体提交,要么在失败时回滚。例如银行转账:它涉及多个步骤,但所有步骤都必须成功或回滚,以避免钱从一个账户中扣除但未添加到另一个账户中。
- 反压
-
反压是阻碍数据流动的力。它确保客户端不会被超出其处理能力的数据量所淹没。
- 事务函数
-
事务函数是由
execute_read
或execute_write
调用执行的回调。在服务器故障的情况下,驱动程序会自动重新执行该回调。 - 驱动程序
-
一个
Driver
对象包含建立与 Neo4j 数据库连接所需的详细信息。