Allow filter on tags

This commit is contained in:
Zoe Roux 2025-01-24 19:17:55 +01:00
parent 426665c9d9
commit ce81caaf14
5 changed files with 25 additions and 23 deletions

View File

@ -44,6 +44,11 @@ const movieFilters: FilterDef = {
runtime: { column: shows.runtime, type: "float" },
airDate: { column: shows.startAir, type: "date" },
originalLanguage: { column: shows.originalLanguage, type: "string" },
tags: {
column: sql.raw(`t.${showTranslations.tags.name}`),
type: "string",
isArray: true,
},
};
export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
@ -284,8 +289,6 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
)
.as("video");
console.log(sort.isDefault)
const items = await db
.select({
...moviesCol,
@ -320,7 +323,7 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
),
)
.orderBy(
...(query && sort.isDefault
...(query // && sort.isDefault
? [sql`word_similarity(${query}::text, ${showTranslations.name})`]
: sortToSql(sort, shows)),
shows.pk,

View File

@ -1,4 +1,4 @@
import { relations, type SQL, sql } from "drizzle-orm";
import { relations, sql } from "drizzle-orm";
import {
check,
date,
@ -12,7 +12,7 @@ import {
uuid,
varchar,
} from "drizzle-orm/pg-core";
import { image, language, schema, tsvector } from "./utils";
import { image, language, schema } from "./utils";
export const showKind = schema.enum("show_kind", ["serie", "movie"]);
export const showStatus = schema.enum("show_status", [
@ -110,21 +110,11 @@ export const showTranslations = schema.table(
banner: image(),
logo: image(),
trailerUrl: text(),
// TODO: use a real language instead of simple here (we could use the `language` column but dic names
// are `english` and not `en`.)
// we'll also need to handle fallback when the language has no dict available on pg.
search: tsvector().generatedAlwaysAs((): SQL => sql`
setweight(to_tsvector('simple', ${showTranslations.name}), 'A') ||
setweight(to_tsvector('simple', array_to_string_im(${showTranslations.aliases}, ' ')), 'B') ||
setweight(to_tsvector('simple', array_to_string_im(${showTranslations.tags}, ' ')), 'C') ||
setweight(to_tsvector('simple', coalesce(${showTranslations.tagline}, '')), 'D') ||
setweight(to_tsvector('simple', coalesce(${showTranslations.description}, '')), 'D')
`),
},
(t) => [
primaryKey({ columns: [t.pk, t.language] }),
index("search").using("gin", t.search),
index("name_trgm").using("gin", sql`${t.name} gin_trgm_ops`),
index("tags").on(t.tags),
],
);

View File

@ -1,4 +1,4 @@
import type { Column } from "drizzle-orm";
import type { Column, SQL } from "drizzle-orm";
import { t } from "elysia";
import { KErrorT } from "~/models/error";
import { comment } from "~/utils";
@ -8,11 +8,11 @@ import { toDrizzle } from "./to-sql";
export type FilterDef = {
[key: string]:
| {
column: Column;
column: Column | SQL;
type: "int" | "float" | "date" | "string";
isArray?: boolean;
}
| { column: Column; type: "enum"; values: string[]; isArray?: boolean };
| { column: Column | SQL; type: "enum"; values: string[]; isArray?: boolean };
};
export const Filter = ({

View File

@ -52,7 +52,6 @@ export const Sort = <
),
)
.Decode((sort): Sort<T, Remap> => {
console.log(sort);
const random = sort.find((x) => x.startsWith("random"));
if (random) {
const seed = random.includes(":")

View File

@ -28,8 +28,7 @@ describe("Get all movies", () => {
expectStatus(resp, body).toBe(422);
expect(body).toMatchObject({
status: 422,
message:
"Invalid property: slug. Expected one of genres, rating, status, runtime, airDate, originalLanguage.",
message: expect.any(String),
details: {
in: "slug eq bubble",
},
@ -277,4 +276,15 @@ describe("Get all movies", () => {
name: dune.translations.en.name,
});
});
it("Filter with tags", async () => {
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);
});
});