diff --git a/api/src/controllers/movies.ts b/api/src/controllers/movies.ts index f94f43ad..eaf21049 100644 --- a/api/src/controllers/movies.ts +++ b/api/src/controllers/movies.ts @@ -317,13 +317,13 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] }) .where( and( filter, - query ? sql`${query}::text %> ${showTranslations.name}` : undefined, + query ? sql`${transQ.name} %> ${query}::text` : undefined, keysetPaginate({ table: shows, after, sort }), ), ) .orderBy( ...(query - ? [sql`word_similarity(${query}::text, ${showTranslations.name})`] + ? [sql`word_similarity(${query}::text, ${transQ.name})`] : sortToSql(sort, shows)), shows.pk, ) diff --git a/api/src/db/index.ts b/api/src/db/index.ts index c2b0d003..07003aac 100644 --- a/api/src/db/index.ts +++ b/api/src/db/index.ts @@ -1,15 +1,30 @@ +import { sql } from "drizzle-orm"; import { drizzle } from "drizzle-orm/node-postgres"; +import { migrate as migrateDb } from "drizzle-orm/node-postgres/migrator"; import * as schema from "./schema"; +const dbConfig = { + user: process.env.POSTGRES_USER ?? "kyoo", + password: process.env.POSTGRES_PASSWORD ?? "password", + database: process.env.POSTGRES_DB ?? "kyooDB", + host: process.env.POSTGRES_SERVER ?? "postgres", + port: Number(process.env.POSTGRES_PORT) || 5432, + ssl: false, +}; export const db = drizzle({ schema, - connection: { - user: process.env.POSTGRES_USER ?? "kyoo", - password: process.env.POSTGRES_PASSWORD ?? "password", - database: process.env.POSTGRES_DB ?? "kyooDB", - host: process.env.POSTGRES_SERVER ?? "postgres", - port: Number(process.env.POSTGRES_PORT) || 5432, - ssl: false, - }, + connection: dbConfig, casing: "snake_case", }); + +export const migrate = async () => { + await db.execute( + sql.raw( + `ALTER DATABASE "${dbConfig.database}" SET pg_trgm.word_similarity_threshold = 0.4;`, + ), + ); + await migrateDb(db, { + migrationsSchema: "kyoo", + migrationsFolder: "./drizzle", + }); +}; diff --git a/api/src/db/schema/utils.ts b/api/src/db/schema/utils.ts index a3126902..24e49251 100644 --- a/api/src/db/schema/utils.ts +++ b/api/src/db/schema/utils.ts @@ -1,4 +1,4 @@ -import { customType, jsonb, pgSchema, varchar } from "drizzle-orm/pg-core"; +import { jsonb, pgSchema, varchar } from "drizzle-orm/pg-core"; export const schema = pgSchema("kyoo"); @@ -6,10 +6,3 @@ export const language = () => varchar({ length: 255 }); export const image = () => jsonb().$type<{ id: string; source: string; blurhash: string }>(); - -// idk why they didn't implement this one -export const tsvector = customType<{ data: string }>({ - dataType() { - return "tsvector"; - }, -}); diff --git a/api/src/index.ts b/api/src/index.ts index 52cbcbe5..e61ad793 100644 --- a/api/src/index.ts +++ b/api/src/index.ts @@ -1,6 +1,5 @@ import jwt from "@elysiajs/jwt"; import { swagger } from "@elysiajs/swagger"; -import { migrate } from "drizzle-orm/node-postgres/migrator"; import { Elysia } from "elysia"; import { base } from "./base"; import { entries } from "./controllers/entries"; @@ -9,11 +8,11 @@ import { seasons } from "./controllers/seasons"; import { seed } from "./controllers/seed"; import { series } from "./controllers/series"; import { videos } from "./controllers/videos"; -import { db } from "./db"; +import { migrate } from "./db"; import { Image } from "./models/utils"; import { comment } from "./utils"; -await migrate(db, { migrationsSchema: "kyoo", migrationsFolder: "./drizzle" }); +await migrate(); let secret = process.env.JWT_SECRET; if (!secret) { diff --git a/api/tests/movies/get-all-movies.test.ts b/api/tests/movies/get-all-movies.test.ts index 6d88ed6c..0397ad4d 100644 --- a/api/tests/movies/get-all-movies.test.ts +++ b/api/tests/movies/get-all-movies.test.ts @@ -280,7 +280,38 @@ describe("Get all movies", () => { const [resp, body] = await getMovies({ limit: 2, filter: "tags eq gravity", - preferOriginal: true, + }); + + expectStatus(resp, body).toBe(200); + expect(body.items).toBeArrayOfSize(1); + expect(body.items[0].slug).toBe(bubble.slug); + }); +}); + +describe("search", () => { + it("Partial match", async () => { + const [resp, body] = await getMovies({ + limit: 2, + query: "bub", + }); + + expectStatus(resp, body).toBe(200); + expect(body.items).toBeArrayOfSize(1); + expect(body.items[0].slug).toBe(bubble.slug); + }); + it("Invalid search don't match", async () => { + const [resp, body] = await getMovies({ + limit: 2, + query: "buboeuoeunhoeu", + }); + + expectStatus(resp, body).toBe(200); + expect(body.items).toBeArrayOfSize(0); + }); + it("Typo match", async () => { + const [resp, body] = await getMovies({ + limit: 2, + query: "bobble", }); expectStatus(resp, body).toBe(200); diff --git a/api/tests/movies/movies-helper.ts b/api/tests/movies/movies-helper.ts index 6d361b60..c5ca4830 100644 --- a/api/tests/movies/movies-helper.ts +++ b/api/tests/movies/movies-helper.ts @@ -33,6 +33,7 @@ export const getMovies = async ({ limit?: number; after?: string; sort?: string | string[]; + query?: string; langs?: string; preferOriginal?: boolean; }) => { diff --git a/api/tests/setup.ts b/api/tests/setup.ts index bd83271a..ab07c363 100644 --- a/api/tests/setup.ts +++ b/api/tests/setup.ts @@ -1,10 +1,6 @@ import { beforeAll } from "bun:test"; -import { migrate } from "drizzle-orm/node-postgres/migrator"; -import { db } from "~/db"; +import { migrate } from "~/db"; beforeAll(async () => { - await migrate(db, { - migrationsSchema: "kyoo", - migrationsFolder: "./drizzle", - }); + await migrate(); });