在 Drizzle schema 中没有专门用于创建扩展的代码。我们假定如果您使用向量类型、索引和查询,您的 PostgreSQL 数据库已经安装了 pg_vector 扩展。
PostgreSQL 扩展
pg_vector
`pg_vector` 是用于 Postgres 的开源向量相似度搜索工具
将您的向量与其余数据一起存储。支持
- 精确和近似最近邻搜索
- 单精度、半精度、二进制和稀疏向量
- L2 距离、内积、余弦距离、L1 距离、汉明距离和 Jaccard 距离
列类型
vector
将您的向量与其余数据一起存储
更多信息请参阅官方 pg_vector **文档**。
const table = pgTable('table', {
embedding: vector({ dimensions: 3 })
})
CREATE TABLE IF NOT EXISTS "table" (
"embedding" vector(3)
);
索引
现在您可以为 `pg_vector` 指定索引,并利用 `pg_vector` 函数进行查询、排序等操作。
我们来看几个来自 `pg_vector` 文档的 `pg_vector` 索引示例,并将它们转换为 Drizzle 表达方式。
L2 距离、内积和余弦距离
// CREATE INDEX ON items USING hnsw (embedding vector_l2_ops);
// CREATE INDEX ON items USING hnsw (embedding vector_ip_ops);
// CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops);
const table = pgTable('items', {
embedding: vector({ dimensions: 3 })
}, (table) => [
index('l2_index').using('hnsw', table.embedding.op('vector_l2_ops'))
index('ip_index').using('hnsw', table.embedding.op('vector_ip_ops'))
index('cosine_index').using('hnsw', table.embedding.op('vector_cosine_ops'))
])
L1 距离、汉明距离和 Jaccard 距离 - 在 pg_vector 0.7.0 版本中添加
// CREATE INDEX ON items USING hnsw (embedding vector_l1_ops);
// CREATE INDEX ON items USING hnsw (embedding bit_hamming_ops);
// CREATE INDEX ON items USING hnsw (embedding bit_jaccard_ops);
const table = pgTable('table', {
embedding: vector({ dimensions: 3 })
}, (table) => [
index('l1_index').using('hnsw', table.embedding.op('vector_l1_ops'))
index('hamming_index').using('hnsw', table.embedding.op('bit_hamming_ops'))
index('bit_jaccard_index').using('hnsw', table.embedding.op('bit_jaccard_ops'))
])
辅助函数
对于查询,您可以使用预定义的向量函数,或使用 SQL 模板运算符创建自定义函数。
您还可以使用以下辅助函数
import { l2Distance, l1Distance, innerProduct,
cosineDistance, hammingDistance, jaccardDistance } from 'drizzle-orm'
l2Distance(table.column, [3, 1, 2]) // table.column <-> '[3, 1, 2]'
l1Distance(table.column, [3, 1, 2]) // table.column <+> '[3, 1, 2]'
innerProduct(table.column, [3, 1, 2]) // table.column <#> '[3, 1, 2]'
cosineDistance(table.column, [3, 1, 2]) // table.column <=> '[3, 1, 2]'
hammingDistance(table.column, '101') // table.column <~> '101'
jaccardDistance(table.column, '101') // table.column <%> '101'
如果 `pg_vector` 有其他可用的函数,您可以复制我们现有函数的实现方式。以下是如何操作:
export function l2Distance(
column: SQLWrapper | AnyColumn,
value: number[] | string[] | TypedQueryBuilder<any> | string,
): SQL {
if (is(value, TypedQueryBuilder<any>) || typeof value === 'string') {
return sql`${column} <-> ${value}`;
}
return sql`${column} <-> ${JSON.stringify(value)}`;
}
您可以随意命名并更改运算符。此示例支持数字数组、字符串数组、字符串,甚至是一个 SELECT 查询。欢迎创建任何其他您想要的类型,或者贡献并提交 PR。
示例
我们来看几个来自 `pg_vector` 文档的 `pg_vector` 查询示例,并将它们转换为 Drizzle 表达方式。
import { l2Distance } from 'drizzle-orm';
// SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;
db.select().from(items).orderBy(l2Distance(items.embedding, [3,1,2]))
// SELECT embedding <-> '[3,1,2]' AS distance FROM items;
db.select({ distance: l2Distance(items.embedding, [3,1,2]) })
// SELECT * FROM items ORDER BY embedding <-> (SELECT embedding FROM items WHERE id = 1) LIMIT 5;
const subquery = db.select({ embedding: items.embedding }).from(items).where(eq(items.id, 1));
db.select().from(items).orderBy(l2Distance(items.embedding, subquery)).limit(5)
// SELECT (embedding <#> '[3,1,2]') * -1 AS inner_product FROM items;
db.select({ innerProduct: sql`(${maxInnerProduct(items.embedding, [3,1,2])}) * -1` }).from(items)
// and more!
postgis
在 Drizzle schema 中没有专门用于创建扩展的代码。我们假定如果您使用 PostGIS 类型、索引和查询,您的 PostgreSQL 数据库已经安装了 `postgis` 扩展。
正如 PostGIS 官网 所述
PostGIS 通过添加对存储、索引和查询地理空间数据的支持,扩展了 PostgreSQL 关系数据库的功能。
如果您在使用 PostGIS 扩展时使用 `introspect` 或 `push` 命令,并且不希望包含 PostGIS 表,您可以使用 `extensionsFilters` 来忽略所有 PostGIS 表。
列类型
geometry
将您的几何数据与其余数据一起存储
更多信息请参阅官方 PostGIS **文档**。
const items = pgTable('items', {
geo: geometry('geo', { type: 'point' }),
geoObj: geometry('geo_obj', { type: 'point', mode: 'xy' }),
geoSrid: geometry('geo_options', { type: 'point', mode: 'xy', srid: 4000 }),
});
模式
`geometry` 类型有两种数据库映射模式:`tuple` 和 `xy`。
- `tuple` 模式在插入时会被接受,并在查询时映射为元组。因此,使用 Drizzle 时,数据库几何数据将被类型化为 `[1,2]`。
- `xy` 模式在插入时会被接受,并在查询时映射为一个包含 x, y 坐标的对象。因此,使用 Drizzle 时,数据库几何数据将被类型化为 `{ x: 1, y: 2 }`。
类型
当前版本有一个预定义的类型:`point`,它对应 PostgreSQL PostGIS 扩展中的 `geometry(Point)` 类型。如果您想使用其他类型,可以在此处指定任何字符串。
索引
借助现有的 Drizzle 索引 API,您应该能够为 PostGIS 编写任何索引。
示例
// CREATE INDEX custom_idx ON table USING GIST (geom);
const table = pgTable('table', {
geo: geometry({ type: 'point' }),
}, (table) => [
index('custom_idx').using('gist', table.geo)
])