数据类型及与 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()` 会丢弃纳秒。

有关时区缩写列表,请参阅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 = '{neo4j-database-uri}';
const USER = '{neo4j-username}';
const PASSWORD = '{neo4j-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,根据其初始化的 `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 = '{neo4j-database-uri}';
const USER = '{neo4j-username}';
const PASSWORD = '{neo4j-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 值和元素之间的映射。`startNodeElementId` 和 `endNodeElementId` 也是如此。

const neo4j = require('neo4j-driver');
const URI = '{neo4j-database-uri}';
const USER = '{neo4j-username}';
const PASSWORD = '{neo4j-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 = '{neo4j-database-uri}';
const USER = '{neo4j-username}';
const PASSWORD = '{neo4j-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

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

最终一致性

如果数据库提供所有集群成员将在某个时间点存储最新版本数据的保证,则称其为最终一致的。

因果一致性

如果读写查询在集群的每个成员中都以相同的顺序可见,则数据库是因果一致的。这比最终一致性更强。

NULL

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

事务

事务是一个工作单元,它要么完整提交,要么在失败时回滚。一个例子是银行转账:它涉及多个步骤,但这些步骤必须全部成功或被撤销,以避免资金从一个账户中扣除但未添加到另一个账户。

背压

背压是一种阻碍数据流动的力。它确保客户端不会因数据流速过快而超载。

事务函数

事务函数是由 executeReadexecuteWrite 调用执行的回调。在服务器故障的情况下,驱动程序会自动重新执行该回调。

驱动程序

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

© . All rights reserved.