You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The pgvector adapter also supports **chunk-aware search** via the `@hasChunks` smart tag — transparently querying across parent and chunk embeddings and returning the minimum distance. See `references/pgvector-adapter.md` for details.
39
+
38
40
Each adapter implements the `SearchAdapter` interface:
39
41
-**`detectColumns()`** — finds searchable columns on a table (e.g. tsvector columns, columns with BM25 indexes)
Tables with the `@hasChunks` smart tag automatically get chunk-aware search. The distance returned is `LEAST(parent_distance, MIN(chunk_distance))` — the best match across the document embedding and all chunk embeddings.
411
+
412
+
Chunk search is **on by default** for `@hasChunks` tables. No extra code is needed:
413
+
414
+
```typescript
415
+
// Chunk-aware search — ON by default for @hasChunks tables
Set `includeChunks: false` to only search the parent embedding:
444
+
445
+
```typescript
446
+
const result =awaitdb.document.findMany({
447
+
where: {
448
+
vectorEmbedding: {
449
+
vector: queryVector,
450
+
metric: 'COSINE',
451
+
includeChunks: false, // only use parent embedding
452
+
},
453
+
},
454
+
orderBy: 'EMBEDDING_DISTANCE_ASC',
455
+
first: 10,
456
+
select: {
457
+
id: true,
458
+
title: true,
459
+
embeddingDistance: true, // parent distance only
460
+
},
461
+
}).execute();
462
+
```
463
+
464
+
### Chunk-Aware Search with Distance Threshold
465
+
466
+
The distance threshold applies to the combined (chunk-aware) distance:
467
+
468
+
```typescript
469
+
const result =awaitdb.document.findMany({
470
+
where: {
471
+
vectorEmbedding: {
472
+
vector: queryVector,
473
+
metric: 'COSINE',
474
+
distance: 0.3, // threshold applies to LEAST(parent, chunk)
475
+
},
476
+
isPublished: { equalTo: true },
477
+
},
478
+
orderBy: 'EMBEDDING_DISTANCE_ASC',
479
+
first: 20,
480
+
select: {
481
+
id: true,
482
+
title: true,
483
+
embeddingDistance: true,
484
+
searchScore: true, // composite 0..1 relevance
485
+
},
486
+
}).execute();
487
+
```
488
+
489
+
> **Note:**`includeChunks` only appears on `VectorNearbyInput` when at least one table in the schema has the `@hasChunks` smart tag. For tables without chunks, the field is absent and vector search behaves as standard parent-only search.
Copy file name to clipboardExpand all lines: skills/graphile-search/references/pgvector-adapter.md
+96Lines changed: 96 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -82,6 +82,102 @@ enum DocumentsOrderBy {
82
82
83
83
pgvector is the only primary adapter that sets `isIntentionalSearch: false`. This is because vector embeddings operate on a different domain than text search — a table with only pgvector columns shouldn't get trgm similarity fields on its text columns.
84
84
85
+
## Chunk-Aware Search (`@hasChunks`)
86
+
87
+
Tables with long-form content (documents, articles, etc.) often split text into **chunks**, each with its own embedding. The pgvector adapter transparently queries across parent and chunk embeddings when the `@hasChunks` smart tag is present on the table's codec.
88
+
89
+
### How It Works
90
+
91
+
1. The parent table has a `vector(N)` column (the document-level embedding)
92
+
2. A separate chunks table stores per-chunk embeddings with a foreign key back to the parent
93
+
3. The `@hasChunks` smart tag tells the adapter where to find the chunks table
94
+
4. At query time, the adapter computes `LEAST(parent_distance, MIN(chunk_distance))` — the best match across all embeddings
95
+
96
+
### Smart Tag Configuration
97
+
98
+
Set `@hasChunks` on the parent table codec as a JSON object:
99
+
100
+
```json
101
+
{
102
+
"chunksTable": "documents_chunks",
103
+
"parentFk": "parent_id",
104
+
"parentPk": "id",
105
+
"embeddingField": "embedding"
106
+
}
107
+
```
108
+
109
+
| Field | Default | Description |
110
+
|-------|---------|-------------|
111
+
|`chunksTable`|*(required)*| Name of the chunks table |
112
+
|`chunksSchema`| parent table's schema | Schema of the chunks table |
113
+
|`parentFk`|`parent_id`| Column in chunks table that references the parent |
114
+
|`parentPk`|`id`| Primary key column on the parent table |
115
+
|`embeddingField`|`embedding`| Vector column in the chunks table |
116
+
117
+
In Constructive, the `DataEmbedding` node type with chunks enabled automatically creates the chunks table and wires up the relationship. The smart tag is applied via a Graphile plugin or smart tags file.
118
+
119
+
### `includeChunks` Filter Field
120
+
121
+
When `@hasChunks` is detected, `VectorNearbyInput` gains an `includeChunks` boolean field:
122
+
123
+
```graphql
124
+
inputVectorNearbyInput {
125
+
vector: [Float!]!
126
+
metric: VectorMetric
127
+
distance: Float
128
+
includeChunks: Boolean # only present when @hasChunks is on the table
129
+
}
130
+
```
131
+
132
+
- **`true` (default for `@hasChunks` tables):** Distance = `LEAST(parent_distance, MIN(chunk_distance))`
0 commit comments