向量

VECTOR 值可以作为节点和关系上的嵌入 (embedding) 属性进行创建和存储,并可使用向量索引GenAI 插件进行高效的语义检索。VECTOR 值还可以使用向量函数进行测量和比较(包括相似度、距离和范数)。

向量类型

VECTOR 类型是一个固定长度、有序的数值集合(INTEGERFLOAT),作为一个单一单元存储。其值的类型定义如下:

  • 维度 (Dimension) — 它所包含的值的数量。

  • 坐标类型 (Coordinate type) — 条目的数据类型,决定了精度和存储大小。

VECTOR 值示例
vector([1.05, 0.123, 5], 3, FLOAT32)

在此示例中,[1.05, 0.123, 5] 是值的列表,3 是其维度,FLOAT32 是单个条目的数据类型。
列表中的每个数字也可以看作是向量维度之一上的一个坐标。

您可以通过函数 toIntegerList()toFloatList() 将向量转换为列表。

有效值

  • VECTOR 值必须具有维度和坐标类型(支持的类型见下表)。

  • VECTOR 值的维度必须大于 0 且小于等于 4096

  • 向量不能包含列表作为元素。

支持的坐标类型
默认名称 别名

FLOAT

FLOAT64

FLOAT32

INTEGER(整数)

INT, INT64, INTEGER64, SIGNED INTEGER

INTEGER32

INT32

INTEGER16

INT16

INTEGER8

INT8

构建向量值

要构建 VECTOR 值,请使用 vector() 函数。

示例 1. 创建一个具有 INTEGER 值的 3 维向量
查询
RETURN vector([1, 2, 3], 3, INTEGER) AS vector
结果
向量 (vector)

vector([1, 2, 3], 3, INTEGER NOT NULL)

行:1

示例 2. 使用参数创建 VECTOR
参数 (LIST<INTEGER>)
{
  "integerList": [1, 2, 3, 4, 5]
}
查询
RETURN vector($integerList, 5, INTEGER8) AS vector
结果
向量 (vector)

vector([1, 2, 3, 4, 5], 5, INTEGER8 NOT NULL)

行:1

将向量值存储为属性

要将 VECTOR 值作为节点或关系属性存储,请使用 vector() 函数和写操作子句。

存储 VECTOR 值要求数据库使用块格式 (block format)。这是 Aura 实例的默认设置。社区版不能将 VECTOR 值作为属性存储。在社区版中,应将嵌入存储为 LIST<INTEGER | FLOAT> 属性,并使用向量索引进行索引。
示例 3. 创建一个节点和一个 VECTOR 属性
查询
CREATE (n:Label {vectorProp: vector([1,2,3], 3, INTEGER)})
RETURN n.vectorProp AS vectorProp
结果
vectorProp

vector([1, 2, 3], 3, INTEGER NOT NULL)

行:1

示例 4. 使用参数创建一个节点和一个 VECTOR 属性
参数
{
  "floatList": [1.3, 2.4, 3.1, 4.4, 5.9]
}
查询
CREATE (n:Label {vectorProp: vector($floatList, 5, FLOAT)})
RETURN n.vectorProp AS vectorProp
结果
vectorProp

vector([1.3, 2.4, 3.1, 4.4, 5.9], 5, FLOAT NOT NULL)

行:1

包含 VECTOR 值作为嵌套条目的列表不能存储为属性。

向量与客户端库(驱动程序)

通过 Neo4j 客户端库处理向量时的行为取决于库的版本。

  • 版本 >= 6.0 — 完全支持向量,并映射到客户端类型(请参阅各语言手册的“数据类型”页面)。

  • 版本 < 6.0 — 向量可以在查询中通过 Cypher® 函数创建、附加和操作,但不能在应用程序中返回或创建。
    可以按照将向量值存储为属性示例中的方法创建和存储值,但返回 VECTOR 会导致得到一个占位符 MAP 值并伴随警告。

    使用 6.0 之前的驱动程序返回 VECTOR 的结果
    +----------------------------------------------------------------+
    | n.vector                                                       |
    +----------------------------------------------------------------+
    | {originalType: "VECTOR(1, INTEGER64)", reason: "UNKNOWN_TYPE"} |
    +----------------------------------------------------------------+
    warn: One or more values returned could not be handled by this version of the driver and were replaced with placeholder map values. Please upgrade your driver!
    03N95 (Neo.ClientNotification.UnknownType)

类型强制转换

强制转换 (Coercion) 是指将不同(隐式)类型的条目强制转换为具有不同坐标类型的向量的操作。

当坐标类型与给定元素的类型相同时,不会进行强制转换。当坐标类型不同时,可能会进行强制转换,或者根据具体情况抛出错误。

如果值不符合坐标类型,则会抛出错误。 如果坐标类型为 INTEGER 类型且所有坐标值均为 INTEGER 值,则仅当其中一个坐标值的大小超出了指定类型的范围时,才会抛出错误。FLOAT 向量类型同理:如果元素全是 FLOAT 值,则仅当其中一个值无法放入指定类型时才会抛出错误。

RETURN VECTOR([128], 1, INT8)
// 22N28: data exception - overflow error. The result of the operation 'vector()' has caused an overflow.
//   22003: data exception - numeric value out of range. The numeric value 128 is outside the required range.

在以下情况中,允许进行强制转换(即有损转换):

  • 列表包含 INTEGER 值,且指定的向量类型为 FLOAT 类型。高位范围的值将会丢失精度(参见 Java 类型规范),但仅在值溢出/下溢时才会抛出错误。

    RETURN VECTOR([987374677], 1, FLOAT32)
    // vector([9.8737466E8], 1, FLOAT32 NOT NULL)
  • 列表包含 FLOAT 值,且指定的类型为 INTEGER 类型。信息可能会丢失,因为小数点后的所有值都将被截断,但仅在值溢出/下溢时才会抛出错误。

    RETURN VECTOR([1.2], 1, INT)
    // vector([1], 1, INTEGER NOT NULL)

超类型

VECTORVECTOR<TYPE>(DIMENSION) 类型的超类型。仅具有坐标类型或维度的 VECTOR 类型也同样适用。

  • 仅定义了维度的 VECTOR 是该维度所有 VECTOR 值的超类型,无论其坐标类型如何。例如,VECTOR(4)VECTOR<FLOAT>(4)VECTOR<INT8>(4) 的超类型。

  • 仅定义了坐标类型的 VECTOR 是该坐标类型所有 VECTOR 值的超类型,无论其维度如何。例如,VECTOR<INT>VECTOR<INT>(3)VECTOR<INT>(1024) 的超类型。

所有这些超类型都可以在类型谓词表达式中使用。更多信息,请参见:

列表、向量嵌入和向量索引

VECTORLIST 值相似,都可以通过向量索引进行索引和搜索,但有几个关键区别:

  • LIST 中的元素可以单独访问,而对 VECTOR 的操作必须作用于整个 VECTOR:无法访问或切片单个元素。

  • 将向量嵌入存储为具有定义坐标类型的 VECTOR 属性可以更有效地存储它们。此外,降低向量的坐标类型(例如从 INTEGER16 降至 INTEGER8)可以减小存储需求并提高性能,前提是所有值保持在较小类型支持的范围内。

您可以通过函数 toIntegerList()toFloatList() 将向量转换为列表。

有关如何使用 GenAI 插件将嵌入存储为 VECTOR 值的更多信息,请参见 GenAI 文档 → 在 Neo4j 数据库中创建和存储嵌入