diff --git a/docs/docs/administration/postgres-standalone.md b/docs/docs/administration/postgres-standalone.md index 84681fdfa6..aa19e28cc1 100644 --- a/docs/docs/administration/postgres-standalone.md +++ b/docs/docs/administration/postgres-standalone.md @@ -81,7 +81,7 @@ VectorChord is the successor extension to pgvecto.rs, allowing for higher perfor ### Migrating from pgvecto.rs -Support for pgvecto.rs will be dropped in a later release, hence we recommend all users currently using pgvecto.rs to migrate to VectorChord at their convenience. There are two primary approaches to do so. +Support for pgvecto.rs has been dropped as of 3.0, hence all users currently using pgvecto.rs should migrate to VectorChord. There are two primary approaches to do so. The easiest option is to have both extensions installed during the migration: diff --git a/docs/docs/install/environment-variables.md b/docs/docs/install/environment-variables.md index b29c233153..1b67637ac0 100644 --- a/docs/docs/install/environment-variables.md +++ b/docs/docs/install/environment-variables.md @@ -81,7 +81,7 @@ Information on the current workers can be found [here](/administration/jobs-work | `DB_PASSWORD` | Database password | `postgres` | server, database\*1 | | `DB_DATABASE_NAME` | Database name | `immich` | server, database\*1 | | `DB_SSL_MODE` | Database SSL mode | | server | -| `DB_VECTOR_EXTENSION`\*2 | Database vector extension (one of [`vectorchord`, `pgvector`, `pgvecto.rs`]) | | server | +| `DB_VECTOR_EXTENSION`\*2 | Database vector extension (one of [`vectorchord`, `pgvector`]) | | server | | `DB_SKIP_MIGRATIONS` | Whether to skip running migrations on startup (one of [`true`, `false`]) | `false` | server | | `DB_STORAGE_TYPE` | Optimize concurrent IO on SSDs or sequential IO on HDDs ([`SSD`, `HDD`])\*3 | `SSD` | database | diff --git a/docs/docs/install/upgrading.md b/docs/docs/install/upgrading.md index 12e5c9c342..38fc056f80 100644 --- a/docs/docs/install/upgrading.md +++ b/docs/docs/install/upgrading.md @@ -130,7 +130,3 @@ These storage mediums have different performance characteristics. As a result, t #### Can I use the new database image as a general PostgreSQL image outside of Immich? It’s a standard PostgreSQL container image that additionally contains the VectorChord, pgvector, and (optionally) pgvecto.rs extensions. If you were using the previous pgvecto.rs image for other purposes, you can similarly do so with this image. - -#### If pgvecto.rs and pgvector still work, why should I switch to VectorChord? - -VectorChord is faster, more stable, uses less RAM, and (with the settings Immich uses) offers higher-quality results than pgvector and pgvecto.rs. This translates to better search and facial recognition experiences. In addition, pgvecto.rs support will be dropped in the future, so changing it sooner will avoid disruption. diff --git a/server/src/constants.ts b/server/src/constants.ts index 20249bf1ca..5af37ef797 100644 --- a/server/src/constants.ts +++ b/server/src/constants.ts @@ -14,7 +14,6 @@ export const ErrorMessages = { export const POSTGRES_VERSION_RANGE = '>=14.0.0'; export const VECTORCHORD_VERSION_RANGE = '>=0.3 <2'; -export const VECTORS_VERSION_RANGE = '>=0.2 <0.4'; export const VECTOR_VERSION_RANGE = '>=0.5 <1'; export const JOBS_ASSET_PAGINATION_SIZE = 1000; @@ -24,15 +23,10 @@ export const EXTENSION_NAMES: Record = { cube: 'cube', earthdistance: 'earthdistance', vector: 'pgvector', - vectors: 'pgvecto.rs', vchord: 'VectorChord', } as const; -export const VECTOR_EXTENSIONS = [ - DatabaseExtension.VectorChord, - DatabaseExtension.Vectors, - DatabaseExtension.Vector, -] as const; +export const VECTOR_EXTENSIONS = [DatabaseExtension.VectorChord, DatabaseExtension.Vector] as const; export const VECTOR_INDEX_TABLES = { [VectorIndex.Clip]: 'smart_search', diff --git a/server/src/dtos/env.dto.ts b/server/src/dtos/env.dto.ts index fc30875b5a..7716c4b30b 100644 --- a/server/src/dtos/env.dto.ts +++ b/server/src/dtos/env.dto.ts @@ -77,7 +77,7 @@ export const EnvSchema = z DB_SSL_MODE: DatabaseSslModeSchema.optional(), DB_URL: z.string().optional(), DB_USERNAME: z.string().optional(), - DB_VECTOR_EXTENSION: z.enum(['pgvector', 'pgvecto.rs', 'vectorchord']).optional(), + DB_VECTOR_EXTENSION: z.enum(['pgvector', 'vectorchord']).optional(), NO_COLOR: z.string().optional(), REDIS_HOSTNAME: z.string().optional(), REDIS_PORT: z.coerce.number().int().optional(), diff --git a/server/src/enum.ts b/server/src/enum.ts index 07b7fe485d..778672424f 100644 --- a/server/src/enum.ts +++ b/server/src/enum.ts @@ -607,7 +607,6 @@ export enum DatabaseExtension { Cube = 'cube', EarthDistance = 'earthdistance', Vector = 'vector', - Vectors = 'vectors', VectorChord = 'vchord', } diff --git a/server/src/repositories/config.repository.ts b/server/src/repositories/config.repository.ts index f6bae39897..ddbdb2a856 100644 --- a/server/src/repositories/config.repository.ts +++ b/server/src/repositories/config.repository.ts @@ -248,10 +248,6 @@ const getEnv = (): EnvData => { vectorExtension = DatabaseExtension.Vector; break; } - case 'pgvecto.rs': { - vectorExtension = DatabaseExtension.Vectors; - break; - } case 'vectorchord': { vectorExtension = DatabaseExtension.VectorChord; break; diff --git a/server/src/repositories/database.repository.ts b/server/src/repositories/database.repository.ts index 7ae1119bbc..a86e929ef4 100644 --- a/server/src/repositories/database.repository.ts +++ b/server/src/repositories/database.repository.ts @@ -1,7 +1,7 @@ import { schemaDiff, schemaFromCode, schemaFromDatabase } from '@immich/sql-tools'; import { Injectable } from '@nestjs/common'; import AsyncLock from 'async-lock'; -import { FileMigrationProvider, Kysely, Migrator, sql, Transaction } from 'kysely'; +import { FileMigrationProvider, Kysely, Migrator, sql } from 'kysely'; import { InjectKysely } from 'nestjs-kysely'; import { readdir } from 'node:fs/promises'; import { join } from 'node:path'; @@ -14,7 +14,6 @@ import { VECTOR_VERSION_RANGE, VECTORCHORD_LIST_SLACK_FACTOR, VECTORCHORD_VERSION_RANGE, - VECTORS_VERSION_RANGE, } from 'src/constants'; import { GenerateSql } from 'src/decorators'; import { DatabaseExtension, DatabaseLock, VectorIndex } from 'src/enum'; @@ -23,7 +22,7 @@ import { LoggingRepository } from 'src/repositories/logging.repository'; import 'src/schema'; // make sure all schema definitions are imported for schemaFromCode import { DB } from 'src/schema'; import { immich_uuid_v7 } from 'src/schema/functions'; -import { ExtensionVersion, VectorExtension, VectorUpdateResult } from 'src/types'; +import { ExtensionVersion, VectorExtension } from 'src/types'; import { vectorIndexQuery } from 'src/utils/database'; import { isValidInteger } from 'src/validation'; @@ -73,7 +72,7 @@ export class DatabaseRepository { return getVectorExtension(this.db); } - @GenerateSql({ params: [[DatabaseExtension.Vectors]] }) + @GenerateSql({ params: [[DatabaseExtension.Vector]] }) async getExtensionVersions(extensions: readonly DatabaseExtension[]): Promise { const { rows } = await sql` SELECT name, default_version as "availableVersion", installed_version as "installedVersion" @@ -88,9 +87,6 @@ export class DatabaseRepository { case DatabaseExtension.VectorChord: { return VECTORCHORD_VERSION_RANGE; } - case DatabaseExtension.Vectors: { - return VECTORS_VERSION_RANGE; - } case DatabaseExtension.Vector: { return VECTOR_VERSION_RANGE; } @@ -125,7 +121,7 @@ export class DatabaseRepository { await sql`DROP EXTENSION IF EXISTS ${sql.raw(extension)}`.execute(this.db); } - async updateVectorExtension(extension: VectorExtension, targetVersion?: string): Promise { + async updateVectorExtension(extension: VectorExtension, targetVersion?: string): Promise { const [{ availableVersion, installedVersion }] = await this.getExtensionVersions([extension]); if (!installedVersion) { throw new Error(`${EXTENSION_NAMES[extension]} extension is not installed`); @@ -136,10 +132,8 @@ export class DatabaseRepository { } targetVersion ??= availableVersion; - let restartRequired = false; - const diff = semver.diff(installedVersion, targetVersion); - if (!diff) { - return { restartRequired: false }; + if (!semver.diff(installedVersion, targetVersion)) { + return; } await Promise.all([ @@ -147,22 +141,8 @@ export class DatabaseRepository { this.db.schema.dropIndex(VectorIndex.Face).ifExists().execute(), ]); - await this.db.transaction().execute(async (tx) => { - await this.setSearchPath(tx); - - await sql`ALTER EXTENSION ${sql.raw(extension)} UPDATE TO ${sql.lit(targetVersion)}`.execute(tx); - - if (extension === DatabaseExtension.Vectors && (diff === 'major' || diff === 'minor')) { - await sql`SELECT pgvectors_upgrade()`.execute(tx); - restartRequired = true; - } - }); - - if (!restartRequired) { - await Promise.all([this.reindexVectors(VectorIndex.Clip), this.reindexVectors(VectorIndex.Face)]); - } - - return { restartRequired }; + await sql`ALTER EXTENSION ${sql.raw(extension)} UPDATE TO ${sql.lit(targetVersion)}`.execute(this.db); + await Promise.all([this.reindexVectors(VectorIndex.Clip), this.reindexVectors(VectorIndex.Face)]); } async prewarm(index: VectorIndex): Promise { @@ -198,12 +178,6 @@ export class DatabaseRepository { } break; } - case DatabaseExtension.Vectors: { - if (!row.indexdef.toLowerCase().includes('using vectors')) { - promises.push(this.reindexVectors(indexName)); - } - break; - } case DatabaseExtension.VectorChord: { const matches = row.indexdef.match(/(?<=lists = \[)\d+/g); const lists = matches && matches.length > 0 ? Number(matches[0]) : 1; @@ -260,11 +234,10 @@ export class DatabaseRepository { await sql`ALTER TABLE ${sql.raw(table)} ADD COLUMN embedding real[] NOT NULL`.execute(tx); } await sql`ALTER TABLE ${sql.raw(table)} ALTER COLUMN embedding SET DATA TYPE real[]`.execute(tx); - const schema = vectorExtension === DatabaseExtension.Vectors ? 'vectors.' : ''; await sql` ALTER TABLE ${sql.raw(table)} ALTER COLUMN embedding - SET DATA TYPE ${sql.raw(schema)}vector(${sql.raw(String(dimSize))})`.execute(tx); + SET DATA TYPE vector(${sql.raw(String(dimSize))})`.execute(tx); await sql.raw(vectorIndexQuery({ vectorExtension, table, indexName, lists })).execute(tx); }); try { @@ -275,10 +248,6 @@ export class DatabaseRepository { this.logger.log(`Reindexed ${indexName}`); } - private async setSearchPath(tx: Transaction): Promise { - await sql`SET search_path TO "$user", public, vectors`.execute(tx); - } - private async getDatabaseName(): Promise { const { rows } = await sql<{ db: string }>`SELECT current_database() as db`.execute(this.db); return rows[0].db; diff --git a/server/src/schema/migrations/1744910873969-InitialMigration.ts b/server/src/schema/migrations/1744910873969-InitialMigration.ts index 530b084f83..9611d878da 100644 --- a/server/src/schema/migrations/1744910873969-InitialMigration.ts +++ b/server/src/schema/migrations/1744910873969-InitialMigration.ts @@ -1,6 +1,5 @@ import { Kysely, sql } from 'kysely'; import { ErrorMessages } from 'src/constants'; -import { DatabaseExtension } from 'src/enum'; import { getVectorExtension } from 'src/repositories/database.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { vectorIndexQuery } from 'src/utils/database'; @@ -107,9 +106,6 @@ export async function up(db: Kysely): Promise { RETURN NULL; END; $$;`.execute(db); - if (vectorExtension === DatabaseExtension.Vectors) { - await sql`SET search_path TO "$user", public, vectors`.execute(db); - } await sql`CREATE TYPE "assets_status_enum" AS ENUM ('active','trashed','deleted');`.execute(db); await sql`CREATE TYPE "sourcetype" AS ENUM ('machine-learning','exif','manual');`.execute(db); await sql`CREATE TABLE "users" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "email" character varying NOT NULL, "password" character varying NOT NULL DEFAULT '', "createdAt" timestamp with time zone NOT NULL DEFAULT now(), "profileImagePath" character varying NOT NULL DEFAULT '', "isAdmin" boolean NOT NULL DEFAULT false, "shouldChangePassword" boolean NOT NULL DEFAULT true, "deletedAt" timestamp with time zone, "oauthId" character varying NOT NULL DEFAULT '', "updatedAt" timestamp with time zone NOT NULL DEFAULT now(), "storageLabel" character varying, "name" character varying NOT NULL DEFAULT '', "quotaSizeInBytes" bigint, "quotaUsageInBytes" bigint NOT NULL DEFAULT 0, "status" character varying NOT NULL DEFAULT 'active', "profileChangedAt" timestamp with time zone NOT NULL DEFAULT now(), "updateId" uuid NOT NULL DEFAULT immich_uuid_v7());`.execute( diff --git a/server/src/services/database.service.spec.ts b/server/src/services/database.service.spec.ts index bae3a705a4..c735d42c5d 100644 --- a/server/src/services/database.service.spec.ts +++ b/server/src/services/database.service.spec.ts @@ -2,7 +2,7 @@ import { EXTENSION_NAMES } from 'src/constants'; import { DatabaseExtension, VectorIndex } from 'src/enum'; import { DatabaseService } from 'src/services/database.service'; import { VectorExtension } from 'src/types'; -import { mockEnvData } from 'test/repositories/config.repository.mock'; +import { envData, mockEnvData } from 'test/repositories/config.repository.mock'; import { newTestService, ServiceMocks } from 'test/utils'; describe(DatabaseService.name, () => { @@ -55,7 +55,6 @@ describe(DatabaseService.name, () => { describe.each(>[ { extension: DatabaseExtension.Vector, extensionName: EXTENSION_NAMES[DatabaseExtension.Vector] }, - { extension: DatabaseExtension.Vectors, extensionName: EXTENSION_NAMES[DatabaseExtension.Vectors] }, { extension: DatabaseExtension.VectorChord, extensionName: EXTENSION_NAMES[DatabaseExtension.VectorChord] }, ])('should work with $extensionName', ({ extension, extensionName }) => { beforeEach(() => { @@ -68,20 +67,7 @@ describe(DatabaseService.name, () => { ]); mocks.database.getVectorExtension.mockResolvedValue(extension); mocks.config.getEnv.mockReturnValue( - mockEnvData({ - database: { - config: { - connectionType: 'parts', - host: 'database', - port: 5432, - username: 'postgres', - password: 'postgres', - database: 'immich', - }, - skipMigrations: false, - vectorExtension: extension, - }, - }), + mockEnvData({ database: { ...envData.database, vectorExtension: extension } }), ); }); @@ -157,7 +143,6 @@ describe(DatabaseService.name, () => { installedVersion: minVersionInRange, }, ]); - mocks.database.updateVectorExtension.mockResolvedValue({ restartRequired: false }); await expect(sut.onBootstrap()).resolves.toBeUndefined(); @@ -278,27 +263,6 @@ describe(DatabaseService.name, () => { expect(mocks.database.runMigrations).not.toHaveBeenCalled(); }); - it(`should warn if ${extension} extension update requires restart`, async () => { - mocks.database.getExtensionVersions.mockResolvedValue([ - { - name: extension, - availableVersion: updateInRange, - installedVersion: minVersionInRange, - }, - ]); - mocks.database.updateVectorExtension.mockResolvedValue({ restartRequired: true }); - - await expect(sut.onBootstrap()).resolves.toBeUndefined(); - - expect(mocks.logger.warn.mock.calls).toEqual( - expect.arrayContaining([expect.arrayContaining([expect.stringContaining(extensionName)])]), - ); - - expect(mocks.database.updateVectorExtension).toHaveBeenCalledWith(extension, updateInRange); - expect(mocks.database.runMigrations).toHaveBeenCalledTimes(1); - expect(mocks.logger.fatal).not.toHaveBeenCalled(); - }); - it(`should reindex ${extension} indices if needed`, async () => { await expect(sut.onBootstrap()).resolves.toBeUndefined(); @@ -329,22 +293,7 @@ describe(DatabaseService.name, () => { }); it('should skip migrations if DB_SKIP_MIGRATIONS=true', async () => { - mocks.config.getEnv.mockReturnValue( - mockEnvData({ - database: { - config: { - connectionType: 'parts', - host: 'database', - port: 5432, - username: 'postgres', - password: 'postgres', - database: 'immich', - }, - skipMigrations: true, - vectorExtension: DatabaseExtension.Vectors, - }, - }), - ); + mocks.config.getEnv.mockReturnValue(mockEnvData({ database: { ...envData.database, skipMigrations: true } })); await expect(sut.onBootstrap()).resolves.toBeUndefined(); @@ -352,7 +301,6 @@ describe(DatabaseService.name, () => { }); it(`should throw error if extension could not be created`, async () => { - mocks.database.updateVectorExtension.mockResolvedValue({ restartRequired: false }); mocks.database.createExtension.mockRejectedValue(new Error('Failed to create extension')); await expect(sut.onBootstrap()).rejects.toThrow('Failed to create extension'); @@ -365,35 +313,42 @@ describe(DatabaseService.name, () => { }); it(`should drop unused extension`, async () => { + mocks.config.getEnv.mockReturnValue( + mockEnvData({ database: { ...envData.database, vectorExtension: DatabaseExtension.Vector } }), + ); + mocks.database.getVectorExtension.mockResolvedValue(DatabaseExtension.Vector); mocks.database.getExtensionVersions.mockResolvedValue([ { - name: DatabaseExtension.Vectors, + name: DatabaseExtension.Vector, installedVersion: minVersionInRange, availableVersion: minVersionInRange, }, { name: DatabaseExtension.VectorChord, - installedVersion: null, + installedVersion: minVersionInRange, availableVersion: minVersionInRange, }, ]); await expect(sut.onBootstrap()).resolves.toBeUndefined(); - expect(mocks.database.createExtension).toHaveBeenCalledExactlyOnceWith(DatabaseExtension.VectorChord); - expect(mocks.database.dropExtension).toHaveBeenCalledExactlyOnceWith(DatabaseExtension.Vectors); + expect(mocks.database.dropExtension).toHaveBeenCalledExactlyOnceWith(DatabaseExtension.VectorChord); }); it(`should warn if unused extension could not be dropped`, async () => { + mocks.config.getEnv.mockReturnValue( + mockEnvData({ database: { ...envData.database, vectorExtension: DatabaseExtension.Vector } }), + ); + mocks.database.getVectorExtension.mockResolvedValue(DatabaseExtension.Vector); mocks.database.getExtensionVersions.mockResolvedValue([ { - name: DatabaseExtension.Vectors, + name: DatabaseExtension.Vector, installedVersion: minVersionInRange, availableVersion: minVersionInRange, }, { name: DatabaseExtension.VectorChord, - installedVersion: null, + installedVersion: minVersionInRange, availableVersion: minVersionInRange, }, ]); @@ -401,10 +356,9 @@ describe(DatabaseService.name, () => { await expect(sut.onBootstrap()).resolves.toBeUndefined(); - expect(mocks.database.createExtension).toHaveBeenCalledExactlyOnceWith(DatabaseExtension.VectorChord); - expect(mocks.database.dropExtension).toHaveBeenCalledExactlyOnceWith(DatabaseExtension.Vectors); + expect(mocks.database.dropExtension).toHaveBeenCalledExactlyOnceWith(DatabaseExtension.VectorChord); expect(mocks.logger.warn).toHaveBeenCalledTimes(1); - expect(mocks.logger.warn.mock.calls[0][0]).toContain('DROP EXTENSION vectors'); + expect(mocks.logger.warn.mock.calls[0][0]).toContain('DROP EXTENSION vchord'); }); it(`should not try to drop pgvector when using vectorchord`, async () => { @@ -426,21 +380,5 @@ describe(DatabaseService.name, () => { expect(mocks.database.dropExtension).not.toHaveBeenCalled(); }); - - it(`should warn if using pgvecto.rs`, async () => { - mocks.database.getExtensionVersions.mockResolvedValue([ - { - name: DatabaseExtension.Vectors, - installedVersion: minVersionInRange, - availableVersion: minVersionInRange, - }, - ]); - mocks.database.getVectorExtension.mockResolvedValue(DatabaseExtension.Vectors); - - await expect(sut.onBootstrap()).resolves.toBeUndefined(); - - expect(mocks.logger.warn).toHaveBeenCalledTimes(1); - expect(mocks.logger.warn.mock.calls[0][0]).toContain('DEPRECATION WARNING'); - }); }); }); diff --git a/server/src/services/database.service.ts b/server/src/services/database.service.ts index 1b2289e6e3..3201f76dab 100644 --- a/server/src/services/database.service.ts +++ b/server/src/services/database.service.ts @@ -9,7 +9,6 @@ import { VectorExtension } from 'src/types'; type CreateFailedArgs = { name: string; extension: string }; type UpdateFailedArgs = { name: string; extension: string; availableVersion: string }; type DropFailedArgs = { name: string; extension: string }; -type RestartRequiredArgs = { name: string; availableVersion: string }; type NightlyVersionArgs = { name: string; extension: string; version: string }; type OutOfRangeArgs = { name: string; extension: string; version: string; range: string }; type InvalidDowngradeArgs = { name: string; extension: string; installedVersion: string; availableVersion: string }; @@ -46,16 +45,10 @@ const messages = { Please run 'DROP EXTENSION ${extension};' manually as a superuser. See https://docs.immich.app/guides/database-queries for how to query the database.`, - restartRequired: ({ name, availableVersion }: RestartRequiredArgs) => - `The ${name} extension has been updated to ${availableVersion}. - Please restart the Postgres instance to complete the update.`, invalidDowngrade: ({ name, installedVersion, availableVersion }: InvalidDowngradeArgs) => `The database currently has ${name} ${installedVersion} activated, but the Postgres instance only has ${availableVersion} available. This most likely means the extension was downgraded. If ${name} ${installedVersion} is compatible with Immich, please ensure the Postgres instance has this available.`, - deprecatedExtension: (name: string) => - `DEPRECATION WARNING: The ${name} extension is deprecated and support for it will be removed very soon. - See https://docs.immich.app/install/upgrading#migrating-to-vectorchord in order to switch to the VectorChord extension instead.`, }; @Injectable() @@ -74,9 +67,6 @@ export class DatabaseService extends BaseService { await this.databaseRepository.withLock(DatabaseLock.Migrations, async () => { const extension = await this.databaseRepository.getVectorExtension(); const name = EXTENSION_NAMES[extension]; - if (extension === DatabaseExtension.Vectors) { - this.logger.warn(messages.deprecatedExtension(name)); - } const extensionRange = this.databaseRepository.getExtensionVersionRange(extension); const extensionVersions = await this.databaseRepository.getExtensionVersions(VECTOR_EXTENSIONS); @@ -156,10 +146,7 @@ export class DatabaseService extends BaseService { private async updateExtension(extension: VectorExtension, availableVersion: string) { this.logger.log(`Updating ${EXTENSION_NAMES[extension]} extension to ${availableVersion}`); try { - const { restartRequired } = await this.databaseRepository.updateVectorExtension(extension, availableVersion); - if (restartRequired) { - this.logger.warn(messages.restartRequired({ name: EXTENSION_NAMES[extension], availableVersion })); - } + await this.databaseRepository.updateVectorExtension(extension, availableVersion); } catch (error) { this.logger.warn(messages.updateFailed({ name: EXTENSION_NAMES[extension], extension, availableVersion })); throw error; diff --git a/server/src/types.ts b/server/src/types.ts index 179f9d1b61..c33b5a18ad 100644 --- a/server/src/types.ts +++ b/server/src/types.ts @@ -394,10 +394,6 @@ export interface ExtensionVersion { installedVersion: string | null; } -export interface VectorUpdateResult { - restartRequired: boolean; -} - export interface ImmichFile extends Express.Multer.File { uuid: string; /** sha1 hash of file */ diff --git a/server/src/utils/database.ts b/server/src/utils/database.ts index 05b1e0b199..837aa9c8d5 100644 --- a/server/src/utils/database.ts +++ b/server/src/utils/database.ts @@ -427,16 +427,6 @@ export function vectorIndexQuery({ vectorExtension, table, indexName, lists }: V sampling_factor = 1024 $$)`; } - case DatabaseExtension.Vectors: { - return ` - CREATE INDEX IF NOT EXISTS ${indexName} ON ${table} - USING vectors (embedding vector_cos_ops) WITH (options = $$ - optimizing.optimizing_threads = 4 - [indexing.hnsw] - m = 16 - ef_construction = 300 - $$)`; - } case DatabaseExtension.Vector: { return ` CREATE INDEX IF NOT EXISTS ${indexName} ON ${table} diff --git a/server/test/repositories/config.repository.mock.ts b/server/test/repositories/config.repository.mock.ts index 797c08c4db..9dd92603c8 100644 --- a/server/test/repositories/config.repository.mock.ts +++ b/server/test/repositories/config.repository.mock.ts @@ -3,7 +3,7 @@ import { ConfigRepository, EnvData } from 'src/repositories/config.repository'; import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -const envData: EnvData = { +export const envData: EnvData = { port: 2283, environment: ImmichEnvironment.Production, logFormat: LogFormat.Console, @@ -30,9 +30,8 @@ const envData: EnvData = { username: 'postgres', password: 'postgres', }, - skipMigrations: false, - vectorExtension: DatabaseExtension.Vectors, + vectorExtension: DatabaseExtension.VectorChord, }, helmet: {