Skip to content

Commit 7ec62ce

Browse files
authored
Vector Index Support (#828)
* Removed duplicate options * Vector index * Vector index test * Updating tests image * Updating changelog * Reverted tests.yml * Rework test * Rework test * Rework test * Rework test * Fixing bug with latest devel (type is sent as "undefined" instead of "") * Making sure test works * Modified changelog
1 parent 5b11d2e commit 7ec62ce

File tree

4 files changed

+139
-33
lines changed

4 files changed

+139
-33
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ This driver uses semantic versioning:
1414
- A change in the major version (e.g. 1.Y.Z -> 2.0.0) indicates _breaking_
1515
changes that require changes in your code to upgrade.
1616

17+
## [10.1.2] - 2025-06-30
18+
19+
### Added
20+
21+
- Added vector index support
22+
1723
## [10.1.1] - 2025-01-13
1824

1925
### Changed

src/collections.ts

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,7 +1466,7 @@ export interface DocumentCollection<
14661466
import(
14671467
data: Buffer | Blob | string,
14681468
options?: documents.ImportDocumentsOptions & {
1469-
type?: "documents" | "list" | "auto";
1469+
type?: "" | "documents" | "list" | "auto";
14701470
}
14711471
): Promise<documents.ImportDocumentsResult>;
14721472
//#endregion
@@ -1612,33 +1612,6 @@ export interface DocumentCollection<
16121612
indexes.MdiIndexDescription & { isNewlyCreated: boolean }
16131613
>
16141614
>;
1615-
/**
1616-
* Creates a prefixed multi-dimensional index on the collection if it does
1617-
* not already exist.
1618-
*
1619-
* @param options - Options for creating the prefixed multi-dimensional index.
1620-
*
1621-
* @example
1622-
* ```js
1623-
* const db = new Database();
1624-
* const collection = db.collection("some-points");
1625-
* // Create a multi-dimensional index for the attributes x, y and z
1626-
* await collection.ensureIndex({
1627-
* type: "mdi-prefixed",
1628-
* fields: ["x", "y", "z"],
1629-
* prefixFields: ["x"],
1630-
* fieldValueTypes: "double"
1631-
* });
1632-
* ```
1633-
* ```
1634-
*/
1635-
ensureIndex(
1636-
options: indexes.EnsureMdiPrefixedIndexOptions
1637-
): Promise<
1638-
connection.ArangoApiResponse<
1639-
indexes.MdiPrefixedIndexDescription & { isNewlyCreated: boolean }
1640-
>
1641-
>;
16421615
/**
16431616
* Creates a prefixed multi-dimensional index on the collection if it does not already exist.
16441617
*
@@ -1712,6 +1685,33 @@ export interface DocumentCollection<
17121685
indexes.InvertedIndexDescription & { isNewlyCreated: boolean }
17131686
>
17141687
>;
1688+
/**
1689+
* Creates a vector index on the collection if it does not already exist.
1690+
*
1691+
* @param options - Options for creating the vector index.
1692+
*
1693+
* @example
1694+
* ```js
1695+
* const db = new Database();
1696+
* const collection = db.collection("some-collection");
1697+
* await collection.ensureIndex({
1698+
* type: "vector",
1699+
* fields: ["embedding"],
1700+
* params: {
1701+
* metric: "cosine",
1702+
* dimension: 128,
1703+
* nLists: 100
1704+
* }
1705+
* });
1706+
* ```
1707+
*/
1708+
ensureIndex(
1709+
options: indexes.EnsureVectorIndexOptions
1710+
): Promise<
1711+
connection.ArangoApiResponse<
1712+
indexes.VectorIndexDescription & { isNewlyCreated: boolean }
1713+
>
1714+
>;
17151715
/**
17161716
* Creates an index on the collection if it does not already exist.
17171717
*
@@ -2296,7 +2296,7 @@ export interface EdgeCollection<
22962296
import(
22972297
data: Buffer | Blob | string,
22982298
options?: documents.ImportDocumentsOptions & {
2299-
type?: "documents" | "list" | "auto";
2299+
type?: "" | "documents" | "list" | "auto";
23002300
}
23012301
): Promise<documents.ImportDocumentsResult>;
23022302
//#endregion
@@ -2875,12 +2875,12 @@ export class Collection<
28752875
import(
28762876
data: Buffer | Blob | string | any[],
28772877
options: documents.ImportDocumentsOptions & {
2878-
type?: "documents" | "list" | "auto";
2878+
type?: "" | "documents" | "list" | "auto";
28792879
} = {}
28802880
): Promise<documents.ImportDocumentsResult> {
28812881
const search = { ...options, collection: this._name };
28822882
if (Array.isArray(data)) {
2883-
search.type = Array.isArray(data[0]) ? undefined : "documents";
2883+
search.type = Array.isArray(data[0]) ? "" : "documents";
28842884
const lines = data as any[];
28852885
data = lines.map((line) => JSON.stringify(line)).join("\r\n") + "\r\n";
28862886
}

src/indexes.ts

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ export type EnsureIndexOptions =
6262
| EnsureTtlIndexOptions
6363
| EnsureMdiIndexOptions
6464
| EnsureMdiPrefixedIndexOptions
65-
| EnsureInvertedIndexOptions;
65+
| EnsureInvertedIndexOptions
66+
| EnsureVectorIndexOptions;
6667

6768
/**
6869
* Shared attributes of all index creation options.
@@ -558,6 +559,56 @@ export type InvertedIndexStoredValueOptions = {
558559
*/
559560
cache?: boolean;
560561
};
562+
563+
/**
564+
* Options for creating a vector index.
565+
*/
566+
export type EnsureVectorIndexOptions = EnsureIndexOptionsType<
567+
"vector",
568+
[string],
569+
{
570+
/**
571+
* The number of threads to use for indexing. Default is 2.
572+
*/
573+
parallelism?: number;
574+
575+
/**
576+
* Vector index parameters, following Faiss configuration.
577+
*/
578+
params: {
579+
/**
580+
* Whether to use cosine or l2 (Euclidean) distance.
581+
*/
582+
metric: "cosine" | "l2";
583+
584+
/**
585+
* Vector dimension. Must match the length of vectors in documents.
586+
*/
587+
dimension: number;
588+
589+
/**
590+
* Number of Voronoi cells (centroids) for IVF. Affects accuracy and index build time.
591+
*/
592+
nLists: number;
593+
594+
/**
595+
* How many neighboring centroids to probe by default. Higher = slower, better recall.
596+
*/
597+
defaultNProbe?: number;
598+
599+
/**
600+
* Training iterations for index build. Default is 25.
601+
*/
602+
trainingIterations?: number;
603+
604+
/**
605+
* Advanced Faiss index factory string.
606+
* If not specified, defaults to IVF<nLists>,Flat.
607+
*/
608+
factory?: string;
609+
};
610+
}
611+
>;
561612
//#endregion
562613

563614
//#region IndexDescription
@@ -572,7 +623,8 @@ export type IndexDescription =
572623
| MdiIndexDescription
573624
| MdiPrefixedIndexDescription
574625
| InvertedIndexDescription
575-
| SystemIndexDescription;
626+
| SystemIndexDescription
627+
| VectorIndexDescription;
576628

577629
/**
578630
* An object representing a system index.
@@ -862,6 +914,26 @@ export type HiddenIndexDescription = (
862914
*/
863915
progress?: number;
864916
};
917+
918+
/**
919+
* An object representing a vector index.
920+
*/
921+
export type VectorIndexDescription = IndexDescriptionType<
922+
"vector",
923+
[string],
924+
{
925+
parallelism: number;
926+
inBackground: boolean;
927+
params: {
928+
metric: "cosine" | "l2";
929+
dimension: number;
930+
nLists: number;
931+
defaultNProbe?: number;
932+
trainingIterations?: number;
933+
factory?: string;
934+
};
935+
}
936+
>;
865937
//#endregion
866938

867939
//#region Index selectors

src/test/11-managing-indexes.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,34 @@ describe("Managing indexes", function () {
2929
system.close();
3030
}
3131
});
32+
describe("collection.ensureIndex#vector", () => {
33+
it.skip("should create a vector index", async () => {
34+
// Available in ArangoDB 3.12.4+.
35+
// Only enabled with the --experimental-vector-index startup option.
36+
const data = Array.from({ length: 128 }, (_, cnt) => ({
37+
_key: `vec${cnt}`,
38+
embedding: Array(128).fill(cnt),
39+
}));
40+
await collection.import(data);
41+
const info = await collection.ensureIndex({
42+
type: "vector",
43+
fields: ["embedding"],
44+
params: {
45+
metric: "cosine",
46+
dimension: 128,
47+
nLists: 2,
48+
},
49+
});
50+
expect(info).to.have.property("id");
51+
expect(info).to.have.property("type", "vector");
52+
expect(info).to.have.property("fields");
53+
expect(info.fields).to.eql(["embedding"]);
54+
expect(info).to.have.property("isNewlyCreated", true);
55+
expect(info).to.have.nested.property("params.metric", "cosine");
56+
expect(info).to.have.nested.property("params.dimension", 128);
57+
expect(info).to.have.nested.property("params.nLists", 2);
58+
});
59+
});
3260
describe("collection.ensureIndex#persistent", () => {
3361
it("should create a persistent index", async () => {
3462
const info = await collection.ensureIndex({

0 commit comments

Comments
 (0)