数据类型及其与 Cypher 类型的映射

本节中的表格显示了 Cypher 数据类型与 JavaScript 类型之间的映射。

核心类型

Cypher 类型 JavaScript 类型

NULL

null

LIST

Array(数组)

MAP

Object(对象)

布尔值 (BOOLEAN)

布尔值

INTEGER(整数)

整数

FLOAT

Number

STRING

字符串

ByteArray

Int8Array

Integer 并非 JavaScript 的原生类型,而是一个为了适应 Cypher 精度要求而设计的自定义类型。在实例化驱动程序时,您可以通过 disableLosslessIntegers 配置项将其禁用,从而改用 JavaScript 原生的 Number 类型。请注意,这可能会导致精度丢失。

时间类型

时间类型数据符合 ISO-8601 标准。若要将其序列化为字符串,请使用 .toString() 方法。时间类型对象是不可变的。

亚秒级数值精确到纳秒。要在驱动程序类型和原生类型之间进行转换,请使用 .fromStandardDate().toStandardDate() 方法(不适用于 Duration)。由于 JavaScript 的日期类型不支持纳秒,.fromStandardDate() 允许传入纳秒参数(可选),而 .toStandardDate() 会舍弃纳秒。

有关时区缩写的列表,请参阅 tz 数据库时区列表

Cypher 类型 JavaScript 类型

DATE

Date

ZONED TIME

Time

LOCAL TIME

LocalTime

ZONED DATETIME

DateTime

LOCAL DATETIME

LocalDateTime

DURATION(持续时间)

Duration

如何在查询中使用时间类型
const neo4j = require('neo4j-driver');
const URI = '<database-uri>';
const USER = '<username>';
const PASSWORD = '<password>';

(async () => {
  const driver = neo4j.driver(URI, neo4j.auth.basic(USER, PASSWORD))

  const friendsSince = new neo4j.types.DateTime(1999, 11, 23, 7, 47, 0, 4123, -4*3600, 'Europe/Berlin')

  // JS native types work as well.
  // They don't support the full feature-set of Neo4j's type though.
  // let jsFriendsSince = new Date(1999, 11, 23, 7, 47, 0)
  // jsFriendsSince = new neo4j.types.Date.fromStandardDate(jsFriendsSince)

  // Create a friendship with the given DateTime, and return the DateTime
  const result = await driver.executeQuery(`
    MERGE (a:Person {name: $name})
    MERGE (b:Person {name: $friend})
    MERGE (a)-[friendship:KNOWS]->(b)
    SET friendship.since = $friendsSince
    RETURN friendship.since
    `, {
      name: 'Alice', friend: 'Bob',
      friendsSince: friendsSince  // or friendsSince: jsFriendsSince
    }
  )
  const outDateTime = result.records[0].get('friendship.since')
  console.log(outDateTime)
  /*
  DateTime {
    year: Integer { low: 1999, high: 0 },
    month: Integer { low: 11, high: 0 },
    day: Integer { low: 23, high: 0 },
    hour: Integer { low: 6, high: 0 },
    minute: Integer { low: 47, high: 0 },
    second: Integer { low: 0, high: 0 },
    nanosecond: Integer { low: 4123, high: 0 },
    timeZoneOffsetSeconds: Integer { low: -18000, high: -1 },
    timeZoneId: 'Europe/Berlin'
  }
 */

  // Convert DateTime to JS native Date (lossy)
  const jsOutDateTime = outDateTime.toStandardDate()
  console.log(jsOutDateTime)
  // 1999-11-23T11:47:00.000Z

  await driver.close()
})()

Date(日期)

表示一个捕获日期但未捕获时间或时区的时刻。

d = new neo4j.Date(2021, 11, 2)
// Date { year: 2021, month: 11, day: 2 }
d.toString() // '2021-11-02'

完整文档请参阅 API 文档 — Date

Time(时间)

表示一个捕获时间及秒级时区偏移量,但未捕获日期的时刻。

d = new neo4j.Time(7, 47, 0, 4123, -4*3600)
/*
Time {
  hour: 7,
  minute: 47,
  second: 0,
  nanosecond: 4123,
  timeZoneOffsetSeconds: -14400
}
*/
d.toString() // '07:47:00.000004123-04:00'

完整文档请参阅 API 文档 — Time

LocalTime(本地时间)

表示一个捕获当日时间,但未捕获日期或时区的时刻。

d = new neo4j.LocalTime(7, 47, 0, 4123)
// LocalTime { hour: 7, minute: 47, second: 0, nanosecond: 4123 }
d.toString() // '07:47:00.000004123'

完整文档请参阅 API 文档 — LocalTime

DateTime(日期时间)

表示一个捕获日期、时间和时区标识符的时刻。时区参数(偏移量和标识符)是可选的。

d = new neo4j.DateTime(2021, 11, 2, 7, 47, 0, 4123, -4*3600, 'Europe/Berlin')
/*
DateTime {
  year: 2021,
  month: 11,
  day: 2,
  hour: 7,
  minute: 47,
  second: 0,
  nanosecond: 4123,
  timeZoneOffsetSeconds: -14400,
  timeZoneId: 'Europe/Berlin'
}
*/
d.toString() // '2021-11-02T07:47:00.000004123-04:00[US/Eastern]'

完整文档请参阅 API 文档 — DateTime

LocalDateTime(本地日期时间)

表示一个捕获日期和时间,但未捕获时区的时刻。

d = new neo4j.LocalDateTime(2021, 11, 2, 7, 47, 0, 4123)
/*
LocalDateTime {
  year: 2021,
  month: 11,
  day: 2,
  hour: 7,
  minute: 47,
  second: 0,
  nanosecond: 4123
}
*/
d.toString() // '2021-11-02T07:47:00.000004123'

完整文档请参阅 API 文档 — LocalDateTime

耗时

表示两个时间点之间的时间差。

const d = new neo4j.Duration(1, 2, 3, 4)
/*
Duration {
  months: 1,
  days: 2,
  seconds: Integer { low: 3, high: 0 },
  nanoseconds: Integer { low: 4, high: 0 }
}
*/
d.toString() // 'P1M2DT3.000000004S'

完整文档请参阅 API 文档 — Duration

空间类型

Cypher 支持空间值(点),Neo4j 可以将这些点值存储为节点和关系的属性。

驱动程序具有单一类型 neo4j.types.Point,根据初始化时使用的 SRID 不同,它可以表现为 2D/3D 笛卡尔坐标点或 WGS-84 坐标点。SRID(空间参考标识符的缩写)是一个用于标识该点所采用坐标系的数字。您可以将其视为每个空间类型的唯一标识符。

SRID 描述

7203

笛卡尔空间中的 2D 点。

9157

笛卡尔空间中的 3D 点。

4326

WGS84 空间中的 2D 点。

4979

WGS84 空间中的 3D 点。

笛卡尔空间中的点
// A 2D Point in cartesian space
const point2d = new neo4j.types.Point(
  7203, // SRID
  1, // x
  5.1 // y
)
// Point { srid: 4979, x: 1, y: -2 }

// A 3D Point in cartesian space
const point3d = new neo4j.types.Point(
  9157, // SRID
  1, // x
  -2, // y
  3.1 // z
)
// Point { srid: 4979, x: 1, y: -2, z: 3.1 }
WGS-84 空间中的点
// A 2D point in WGS-84 space
const point2d = new neo4j.types.Point(
  4326, // SRID
  1, // x
  -2, // y
  3.1 // z
)
// Point { srid: 4979, x: 1, y: -2}

// A 3D point in WGS-84 space
const point3d = new neo4j.types.Point(
  4979, // SRID
  1, // x
  -2, // y
  3.1 // z
)
// Point { srid: 4979, x: 1, y: -2, z: 3.1 }

完整文档请参阅 API 文档 — Point

图类型

图类型仅作为结果传递,不可用作参数.

Cypher 类型 JavaScript 类型

NODE

neo4j.types.Node(节点)

RELATIONSHIP

neo4j.types.Relationship(关系)

PATH

neo4j.types.Path(路径)

neo4j.types.PathSegment(路径片段)

Node

表示图中的一个节点。
属性 elementId 提供了实体的标识符。使用时应小心,因为不保证 ID 值与事务范围之外的元素之间的映射关系。换句话说,使用 elementId 在不同事务之间 MATCH 元素是有风险的。

const neo4j = require('neo4j-driver');
const URI = '<database-uri>';
const USER = '<username>';
const PASSWORD = '<password>';

(async () => {
  const driver = neo4j.driver(URI, neo4j.auth.basic(USER, PASSWORD))
  const result = await driver.executeQuery(
    'MERGE (p:Person {name: $name}) RETURN p AS person',
    { name: 'Alice' }
  )
  const node = result.records[0].get('person')
  console.log(node)
  /*
  Node {
    identity: Integer { low: 393, high: 0 },  // deprecated
    labels: [ 'Person' ],
    properties: { name: 'Alice' },
    elementId: '4:d6154461-ff34-42a9-b7c3-d32673913419:393'
  }
  */
  await driver.close()
})()

完整文档请参阅 API 文档 — Node

Relationship

表示图中的一个关系。
属性 elementId 提供了实体的标识符。使用时应小心,因为不保证 ID 值与事务范围之外的元素之间的映射关系。这也适用于 startNodeElementIdendNodeElementId

const neo4j = require('neo4j-driver');
const URI = '<database-uri>';
const USER = '<username>';
const PASSWORD = '<password>';

(async () => {
  const driver = neo4j.driver(URI, neo4j.auth.basic(USER, PASSWORD))
  const result = await driver.executeQuery(`
    MERGE (p:Person {name: $name})
    MERGE (friend:Person {name: $friend_name})
    MERGE (p)-[r:KNOWS]->(friend)
    SET r.status = $status, r.since = date()
    RETURN r AS friendship
    `, {
      name: 'Alice', status: 'BFF', friend_name: 'Bob'
    }
  )
  const relationship = result.records[0].get('friendship')
  console.log(relationship)
  /*
  Relationship {
    identity: Integer { low: 388, high: 0 },  // deprecated
    start: Integer { low: 393, high: 0 },  // deprecated
    end: Integer { low: 394, high: 0 },  // deprecated
    type: 'KNOWS',
    properties: {
      since: Date { year: [Integer], month: [Integer], day: [Integer] },
      status: 'BFF'
    },
    elementId: '5:d6154461-ff34-42a9-b7c3-d32673913419:388',
    startNodeElementId: '4:d6154461-ff34-42a9-b7c3-d32673913419:393',
    endNodeElementId: '4:d6154461-ff34-42a9-b7c3-d32673913419:394'
  }
  */
  await driver.close()
})()

完整文档请参阅 API 文档 — Relationship

Path, PathSegment

Path 表示图中的一条路径,而 PathSegment 表示其各个链接。

const neo4j = require('neo4j-driver');
const URI = '<database-uri>';
const USER = '<username>';
const PASSWORD = '<password>';

(async () => {
  const driver = neo4j.driver(URI, neo4j.auth.basic(USER, PASSWORD))

  // Create some :Person nodes linked by :KNOWS relationships
  await addFriend(driver, 'Alice', 'BFF', 'Bob')
  await addFriend(driver, 'Bob', 'Fiends', 'Sofia')
  await addFriend(driver, 'Sofia', 'Acquaintances', 'Sara')

  // Follow :KNOWS relationships outgoing from Alice three times, return as path
  const result = await driver.executeQuery(`
    MATCH p = (:Person {name: $name})-[:KNOWS*3]->(:Person)
    RETURN p AS friendsChain
    `, {
      name: 'Alice'
    }
  )
  const path = result.records[0].get('friendsChain')
  console.log(path)
  /*
  Path {
    start: Node {
      identity: Integer { low: 393, high: 0 },
      labels: [ 'Person' ],
      properties: { name: 'Alice' },
      elementId: '4:d6154461-ff34-42a9-b7c3-d32673913419:393'
    },
    end: Node {
      identity: Integer { low: 396, high: 0 },
      labels: [ 'Person' ],
      properties: { name: 'Sara' },
      elementId: '4:d6154461-ff34-42a9-b7c3-d32673913419:396'
    },
    segments: [
      PathSegment {
        start: [Node],
        relationship: [Relationship],
        end: [Node]
      },
      PathSegment {
        start: [Node],
        relationship: [Relationship],
        end: [Node]
      },
      PathSegment {
        start: [Node],
        relationship: [Relationship],
        end: [Node]
      }
    ],
    length: 3
  }
  */
  await driver.close()
})()

async function addFriend(driver, name, status, friendName) {
  await driver.executeQuery(`
    MERGE (p:Person {name: $name})
    MERGE (friend:Person {name: $friendName})
    MERGE (p)-[r:KNOWS]->(friend)
    SET r.status = $status, r.since = date()
    `, {
      name: name, status: status, friendName: friendName
    }
  )
}

完整文档请参阅 API 文档 — PathPathSegment

向量类型

类型 Vector 映射到 Cypher 类型 VECTORVector 对象存储为包含同质值的连续内存块。

vector 构造函数接受一个 Javascript TypedArray。支持的 TypedArray 对象包括:Int8Array, Int16Array, Int32Array, Int64Array, Float32Array, Float64Array

创建并存储向量
// Create a vector
var typedArray = Float32Array.from([1, 2, 3])
var neo4jVector = neo4j.vector(typedArray)  (1)

// Store the vector as a node property
await driver.executeQuery('MERGE (d:Doc {embedding: $vector})', { vector: neo4jVector })
在数据库中存储 VECTOR 对象需要服务器版本 >= 2025.10,企业版。
检索并处理向量
// Retrieve a vector
var { records } = await driver.executeQuery(
  "MATCH (d:Doc) RETURN d.embedding AS v LIMIT 1"
)
var neo4jVector = records[0].get("v")

console.log(neo4jVector.toString())
// vector([1, 2, 3], 3, FLOAT32 NOT NULL)

// Get a TypedArray of the same type as the Vector
var retrievedTypedArray = neo4jVector.asTypedArray()

// Convert the TypedArray into a regular array of Numbers (not safe for Int64 arrays)
var retrievedArray = Array.from(retrievedTypedArray)
普通 Javascript 数组在转换为字符串时会被截断,而 Vector 类型总是显示所有元素。记录 Vector 对象可能会导致日志过载或引发内存溢出 (OOM) 错误。

UnsupportedType

类型 UnsupportedType 用于表示 Cypher 查询返回但驱动程序无法识别的数据类型。当客户端版本相对于服务器版本过旧时,会出现这种情况。

术语表

LTS (长期支持版)

长期支持 (Long Term Support) 版本是保证在若干年内得到支持的版本。Neo4j 4.4 和 5.26 是 LTS 版本。

Aura

Aura 是 Neo4j 的全托管云服务。它提供免费和付费计划。

Cypher

Cypher 是 Neo4j 的图查询语言,允许您从数据库中检索数据。它就像 SQL,但专用于图数据库。

APOC

Awesome Procedures On Cypher (APOC) 是一个包含(许多)函数的库,这些函数在 Cypher 本身中难以轻松实现。

Bolt

Bolt 是用于 Neo4j 实例和驱动程序之间交互的协议。默认监听 7687 端口。

ACID

原子性 (Atomicity)、一致性 (Consistency)、隔离性 (Isolation)、持久性 (Durability) (ACID) 是保证数据库事务可靠处理的属性。符合 ACID 的 DBMS 确保即使发生故障,数据库中的数据也能保持准确和一致。

最终一致性

如果一个数据库能保证所有集群成员在某个时间点都存储了数据的最新版本,则该数据库具有最终一致性。

因果一致性

如果读写查询被集群中的每个成员以相同的顺序看到,则数据库具有因果一致性。这比最终一致性更强。

NULL

空标记不是一种类型,而是缺失值的占位符。更多信息,请参阅 Cypher → 使用 null

事务

事务是一个工作单元,要么被提交,要么在失败时被回滚。例如银行转账:它涉及多个步骤,但它们必须全部成功或全部撤销,以避免钱从一个账户扣除却未存入另一个账户的情况。

背压

背压是对数据流的抵抗力。它确保客户端不会被过快发送的数据压垮,从而超出其处理能力。

书签

书签是代表数据库某种状态的标记。通过将一个或多个书签与查询一起传递,服务器将确保在所表示的状态建立之前,该查询不会被执行。

事务函数

事务函数是由 executeReadexecuteWrite 调用执行的回调。如果发生服务器故障,驱动程序会自动重新执行该回调。

驱动程序 (Driver)

Driver 对象保存了与 Neo4j 数据库建立连接所需的详细信息。