graphile-search 1.5.2 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adapters/pgvector.js +17 -10
- package/esm/adapters/pgvector.js +17 -10
- package/package.json +12 -12
package/adapters/pgvector.js
CHANGED
|
@@ -9,13 +9,20 @@
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.createPgvectorAdapter = createPgvectorAdapter;
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* Build a distance expression for the given metric.
|
|
13
|
+
* Uses explicit SQL template literals for each operator to avoid sql.raw.
|
|
13
14
|
*/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
function buildDistanceExpr(sql, columnExpr, vectorExpr, metric) {
|
|
16
|
+
switch (metric) {
|
|
17
|
+
case 'L2':
|
|
18
|
+
return sql `(${columnExpr} <-> ${vectorExpr})`;
|
|
19
|
+
case 'IP':
|
|
20
|
+
return sql `(${columnExpr} <#> ${vectorExpr})`;
|
|
21
|
+
case 'COSINE':
|
|
22
|
+
default:
|
|
23
|
+
return sql `(${columnExpr} <=> ${vectorExpr})`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
19
26
|
function isVectorCodec(codec) {
|
|
20
27
|
return codec?.name === 'vector';
|
|
21
28
|
}
|
|
@@ -171,7 +178,6 @@ function createPgvectorAdapter(options = {}) {
|
|
|
171
178
|
if (!vector || !Array.isArray(vector) || vector.length === 0)
|
|
172
179
|
return null;
|
|
173
180
|
const resolvedMetric = metric || defaultMetric;
|
|
174
|
-
const operator = METRIC_OPERATORS[resolvedMetric] || METRIC_OPERATORS.COSINE;
|
|
175
181
|
const vectorString = `[${vector.join(',')}]`;
|
|
176
182
|
const vectorExpr = sql `${sql.value(vectorString)}::vector`;
|
|
177
183
|
// Check if this column has chunks info and chunk querying is requested
|
|
@@ -190,14 +196,15 @@ function createPgvectorAdapter(options = {}) {
|
|
|
190
196
|
// Alias to avoid ambiguity when the chunks table name might collide
|
|
191
197
|
const chunksAlias = sql.identifier('__chunks');
|
|
192
198
|
// Subquery: SELECT MIN(distance) FROM chunks WHERE chunks.parent_fk = parent.pk
|
|
199
|
+
const chunkDistanceExpr = buildDistanceExpr(sql, sql `${chunksAlias}.${chunkEmbedding}`, vectorExpr, resolvedMetric);
|
|
193
200
|
const chunkDistanceSubquery = sql `(
|
|
194
|
-
SELECT MIN(${
|
|
201
|
+
SELECT MIN(${chunkDistanceExpr})
|
|
195
202
|
FROM ${chunksTableRef} AS ${chunksAlias}
|
|
196
203
|
WHERE ${chunksAlias}.${parentFk} = ${parentId}
|
|
197
204
|
)`;
|
|
198
205
|
// Also compute direct parent distance if the parent has an embedding
|
|
199
206
|
const parentColumnExpr = sql `${alias}.${sql.identifier(column.attributeName)}`;
|
|
200
|
-
const parentDistanceExpr = sql
|
|
207
|
+
const parentDistanceExpr = buildDistanceExpr(sql, parentColumnExpr, vectorExpr, resolvedMetric);
|
|
201
208
|
// Use LEAST of parent distance and closest chunk distance
|
|
202
209
|
// COALESCE handles cases where parent or chunks may not have embeddings
|
|
203
210
|
const combinedDistanceExpr = sql `LEAST(
|
|
@@ -215,7 +222,7 @@ function createPgvectorAdapter(options = {}) {
|
|
|
215
222
|
}
|
|
216
223
|
// Standard (non-chunk) query
|
|
217
224
|
const columnExpr = sql `${alias}.${sql.identifier(column.attributeName)}`;
|
|
218
|
-
const distanceExpr = sql
|
|
225
|
+
const distanceExpr = buildDistanceExpr(sql, columnExpr, vectorExpr, resolvedMetric);
|
|
219
226
|
let whereClause = null;
|
|
220
227
|
if (distance !== undefined && distance !== null) {
|
|
221
228
|
whereClause = sql `${distanceExpr} <= ${sql.value(distance)}`;
|
package/esm/adapters/pgvector.js
CHANGED
|
@@ -6,13 +6,20 @@
|
|
|
6
6
|
* Wraps the same SQL logic as graphile-pgvector but as a SearchAdapter.
|
|
7
7
|
*/
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Build a distance expression for the given metric.
|
|
10
|
+
* Uses explicit SQL template literals for each operator to avoid sql.raw.
|
|
10
11
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
function buildDistanceExpr(sql, columnExpr, vectorExpr, metric) {
|
|
13
|
+
switch (metric) {
|
|
14
|
+
case 'L2':
|
|
15
|
+
return sql `(${columnExpr} <-> ${vectorExpr})`;
|
|
16
|
+
case 'IP':
|
|
17
|
+
return sql `(${columnExpr} <#> ${vectorExpr})`;
|
|
18
|
+
case 'COSINE':
|
|
19
|
+
default:
|
|
20
|
+
return sql `(${columnExpr} <=> ${vectorExpr})`;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
16
23
|
function isVectorCodec(codec) {
|
|
17
24
|
return codec?.name === 'vector';
|
|
18
25
|
}
|
|
@@ -168,7 +175,6 @@ export function createPgvectorAdapter(options = {}) {
|
|
|
168
175
|
if (!vector || !Array.isArray(vector) || vector.length === 0)
|
|
169
176
|
return null;
|
|
170
177
|
const resolvedMetric = metric || defaultMetric;
|
|
171
|
-
const operator = METRIC_OPERATORS[resolvedMetric] || METRIC_OPERATORS.COSINE;
|
|
172
178
|
const vectorString = `[${vector.join(',')}]`;
|
|
173
179
|
const vectorExpr = sql `${sql.value(vectorString)}::vector`;
|
|
174
180
|
// Check if this column has chunks info and chunk querying is requested
|
|
@@ -187,14 +193,15 @@ export function createPgvectorAdapter(options = {}) {
|
|
|
187
193
|
// Alias to avoid ambiguity when the chunks table name might collide
|
|
188
194
|
const chunksAlias = sql.identifier('__chunks');
|
|
189
195
|
// Subquery: SELECT MIN(distance) FROM chunks WHERE chunks.parent_fk = parent.pk
|
|
196
|
+
const chunkDistanceExpr = buildDistanceExpr(sql, sql `${chunksAlias}.${chunkEmbedding}`, vectorExpr, resolvedMetric);
|
|
190
197
|
const chunkDistanceSubquery = sql `(
|
|
191
|
-
SELECT MIN(${
|
|
198
|
+
SELECT MIN(${chunkDistanceExpr})
|
|
192
199
|
FROM ${chunksTableRef} AS ${chunksAlias}
|
|
193
200
|
WHERE ${chunksAlias}.${parentFk} = ${parentId}
|
|
194
201
|
)`;
|
|
195
202
|
// Also compute direct parent distance if the parent has an embedding
|
|
196
203
|
const parentColumnExpr = sql `${alias}.${sql.identifier(column.attributeName)}`;
|
|
197
|
-
const parentDistanceExpr = sql
|
|
204
|
+
const parentDistanceExpr = buildDistanceExpr(sql, parentColumnExpr, vectorExpr, resolvedMetric);
|
|
198
205
|
// Use LEAST of parent distance and closest chunk distance
|
|
199
206
|
// COALESCE handles cases where parent or chunks may not have embeddings
|
|
200
207
|
const combinedDistanceExpr = sql `LEAST(
|
|
@@ -212,7 +219,7 @@ export function createPgvectorAdapter(options = {}) {
|
|
|
212
219
|
}
|
|
213
220
|
// Standard (non-chunk) query
|
|
214
221
|
const columnExpr = sql `${alias}.${sql.identifier(column.attributeName)}`;
|
|
215
|
-
const distanceExpr = sql
|
|
222
|
+
const distanceExpr = buildDistanceExpr(sql, columnExpr, vectorExpr, resolvedMetric);
|
|
216
223
|
let whereClause = null;
|
|
217
224
|
if (distance !== undefined && distance !== null) {
|
|
218
225
|
whereClause = sql `${distanceExpr} <= ${sql.value(distance)}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "graphile-search",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.3",
|
|
4
4
|
"description": "Unified PostGraphile v5 search plugin — abstracts tsvector, BM25, pg_trgm, and pgvector behind a single adapter-based architecture with composite searchScore",
|
|
5
5
|
"author": "Constructive <developers@constructive.io>",
|
|
6
6
|
"homepage": "https://github.com/constructive-io/constructive",
|
|
@@ -31,20 +31,20 @@
|
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^22.19.11",
|
|
33
33
|
"@types/pg": "^8.18.0",
|
|
34
|
-
"graphile-connection-filter": "^1.3.
|
|
35
|
-
"graphile-test": "^4.7.
|
|
36
|
-
"makage": "^0.
|
|
34
|
+
"graphile-connection-filter": "^1.3.3",
|
|
35
|
+
"graphile-test": "^4.7.3",
|
|
36
|
+
"makage": "^0.3.0",
|
|
37
37
|
"pg": "^8.20.0",
|
|
38
|
-
"pgsql-test": "^4.7.
|
|
38
|
+
"pgsql-test": "^4.7.3"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@dataplan/pg": "1.0.0
|
|
42
|
-
"graphile-build": "5.0.0
|
|
43
|
-
"graphile-build-pg": "5.0.0
|
|
44
|
-
"graphile-config": "1.0.0
|
|
41
|
+
"@dataplan/pg": "1.0.0",
|
|
42
|
+
"graphile-build": "5.0.0",
|
|
43
|
+
"graphile-build-pg": "5.0.0",
|
|
44
|
+
"graphile-config": "1.0.0",
|
|
45
45
|
"graphql": "16.13.0",
|
|
46
|
-
"pg-sql2": "5.0.0
|
|
47
|
-
"postgraphile": "5.0.0
|
|
46
|
+
"pg-sql2": "5.0.0",
|
|
47
|
+
"postgraphile": "5.0.0"
|
|
48
48
|
},
|
|
49
49
|
"keywords": [
|
|
50
50
|
"postgraphile",
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"hybrid-search",
|
|
63
63
|
"searchScore"
|
|
64
64
|
],
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "baae875effd00af36577612c861d0f6f9a1a792a"
|
|
66
66
|
}
|