数据类型和 Cypher 类型映射

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

核心类型

Cypher 类型 JavaScript 类型

NULL

null

LIST

Array

MAP

Object

BOOLEAN

Boolean

INTEGER

Integer

FLOAT

Number

STRING

String

ByteArray

Int8Array

Integer 不是 JavaScript 的原生类型之一,而是一个自定义类型,用于适应 Cypher 的精度。在实例化驱动程序时,您可以通过 disableLosslessIntegers 配置项 禁用此功能,以便使用 JavaScript 的原生 Number 类型。请注意,这可能导致精度损失。

时间类型

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

亚秒级值以纳秒精度测量。要转换驱动程序和原生类型,请使用 .fromStandardDate().toStandardDate() 方法(不适用于 Duration)。由于 JavaScript 日期类型不支持纳秒,因此 .fromStandardDate() 允许使用纳秒参数(可选),而 .toStandardDate() 会删除纳秒。

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

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 = '<URI for Neo4j database>';
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

Duration

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

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,它可以充当 2D/3D 笛卡尔/WGS-84 点,具体取决于初始化它的 SRIDSRID(空间参考标识符的缩写)是识别要解释点的坐标系的数字。您可以将其视为每个空间类型的唯一标识符。

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 值和元素之间的映射。换句话说,跨不同事务使用 elementIdMATCH 元素是有风险的。

const neo4j = require('neo4j-driver');
const URI = '<URI for Neo4j database>';
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 = '<URI for Neo4j database>';
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 = '<URI for Neo4j database>';
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

错误

驱动程序引发的所有错误都属于 Neo4jError 类型。有关服务器可以返回的错误列表,请参阅 状态码 页面。

某些服务器错误被标记为可以安全重试,无需更改原始请求。此类错误的示例包括死锁、内存问题或连接问题。所有驱动程序的异常类型都实现了 .isRetryable() 方法,该方法提供了有关进一步尝试是否可能成功的见解。这在 显式事务 中运行查询时特别有用,以便了解是否应再次运行失败的查询。

术语表

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

事务

事务是工作单元,要么完全提交,要么在失败时回滚。例如银行转账:它涉及多个步骤,但这些步骤必须全部成功或回退,以避免从一个账户中扣款但没有添加到另一个账户中。

背压

背压是一种对抗数据流动的力。它确保客户端不会被超出其处理能力的数据淹没。

事务函数

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

驱动程序

一个 Driver 对象包含建立与 Neo4j 数据库连接所需的详细信息。