mirror of
https://github.com/BradNut/boredgame
synced 2025-09-08 17:40:22 +00:00
Changing search to currently just search by like. Adding functions to get order by and direction based on search inputs.
This commit is contained in:
parent
45e9e5adb7
commit
0b58b3ff8f
9 changed files with 195 additions and 347 deletions
473
pnpm-lock.yaml
473
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
|
@ -1,8 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { superForm, type Infer, type SuperValidated } from 'sveltekit-superforms';
|
||||
import { search_schema, type SearchSchema } from '$lib/zodValidation';
|
||||
import * as Form from "$lib/components/ui/form";
|
||||
import { zodClient } from 'sveltekit-superforms/adapters';
|
||||
import { search_schema, type SearchSchema } from '$lib/zodValidation';
|
||||
import * as Form from "$lib/components/ui/form";
|
||||
import Input from '$components/ui/input/input.svelte';
|
||||
import Checkbox from '$components/ui/checkbox/checkbox.svelte';
|
||||
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ export async function createOrUpdateGameMinimal(locals: App.Locals, game: Games,
|
|||
.insert(games)
|
||||
.values({
|
||||
name: game.name,
|
||||
slug: kebabCase(game.name || game.slug || ''),
|
||||
slug: kebabCase(game.name ?? game.slug ?? ''),
|
||||
description: game.description,
|
||||
year_published: game.year_published,
|
||||
url: externalUrl,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ async function searchForGames(
|
|||
method: 'GET',
|
||||
headers
|
||||
};
|
||||
const url = `/api/game/search${urlQueryParams ? `?${urlQueryParams}` : ''}`;
|
||||
const url = `/api/games/search${urlQueryParams ? `?${urlQueryParams}` : ''}`;
|
||||
console.log('Calling internal api', url);
|
||||
const response = await eventFetch(url, requestInit);
|
||||
console.log('response from internal api', response);
|
||||
|
|
@ -44,9 +44,9 @@ async function searchForGames(
|
|||
!games.find((game: GameType) => game.slug === kebabCase(gameNameSearch))
|
||||
) {
|
||||
console.log('No games found in DB for', gameNameSearch);
|
||||
|
||||
const searchQueryParams = urlQueryParams ? `?${urlQueryParams}` : '';
|
||||
const externalResponse = await eventFetch(
|
||||
`/api/external/search${urlQueryParams ? `?${urlQueryParams}` : ''}`,
|
||||
`/api/external/search${searchQueryParams}`,
|
||||
requestInit
|
||||
);
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ const defaults = {
|
|||
exact: false,
|
||||
};
|
||||
|
||||
export const load: PageServerLoad = async ({ locals, fetch, url }) => {
|
||||
export const load = async ({ locals, fetch, url }) => {
|
||||
const searchParams = Object.fromEntries(url?.searchParams);
|
||||
console.log('searchParams', searchParams);
|
||||
searchParams.order = searchParams.order || defaults.order;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { fail, error, type Actions } from '@sveltejs/kit';
|
||||
import { and, eq, ne } from 'drizzle-orm';
|
||||
import { and, eq } from 'drizzle-orm';
|
||||
import { Argon2id } from 'oslo/password';
|
||||
import { decodeHex } from 'oslo/encoding';
|
||||
import { TOTPController } from 'oslo/otp';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { error, json } from '@sveltejs/kit';
|
||||
import db from '$lib/drizzle.js';
|
||||
import { eq, sql } from 'drizzle-orm';
|
||||
import {asc, desc, eq, ilike, or } from 'drizzle-orm';
|
||||
import { games } from '../../../../schema.js';
|
||||
import kebabCase from "just-kebab-case";
|
||||
|
||||
// Search a user's collection
|
||||
export const GET = async ({ url, locals }) => {
|
||||
|
|
@ -9,14 +10,14 @@ export const GET = async ({ url, locals }) => {
|
|||
const q = searchParams?.q?.trim() || '';
|
||||
const limit = parseInt(searchParams?.limit) || 10;
|
||||
const skip = parseInt(searchParams?.skip) || 0;
|
||||
const order = searchParams?.order || 'desc';
|
||||
const order: OrderDirection = searchParams?.order === 'desc' ? 'desc' : 'asc';
|
||||
const exact = searchParams?.exact === 'true';
|
||||
let orderBy = searchParams?.orderBy || 'slug';
|
||||
|
||||
if (orderBy === 'name') {
|
||||
orderBy = 'slug';
|
||||
}
|
||||
console.log(`q: ${q}, limit: ${limit}, skip: ${skip}, order: ${order}, exact: ${exact}`);
|
||||
console.log(`q: ${q}, limit: ${limit}, skip: ${skip}, order: ${order}, exact: ${exact}, orderBy: ${orderBy}`);
|
||||
console.log(exact);
|
||||
if (exact) {
|
||||
console.log('Exact Search API');
|
||||
|
|
@ -44,9 +45,23 @@ export const GET = async ({ url, locals }) => {
|
|||
slug: games.slug,
|
||||
thumb_url: games.thumb_url
|
||||
})
|
||||
.from(games)
|
||||
.where(sql`to_tsvector('simple', ${games.name}) || to_tsvector('simple', ${games.slug}) @@ to_tsquery('simple', ${q})`)
|
||||
.orderBy(sql`${orderBy} ${order}`).offset(skip).limit(limit) || [];
|
||||
.from(games)
|
||||
.where(or(
|
||||
ilike(games.name, `%${q}%`),
|
||||
ilike(games.slug, `%${kebabCase(q)}%`)
|
||||
))
|
||||
.orderBy(getOrderDirection(order)(getOrderBy(orderBy)))
|
||||
.offset(skip)
|
||||
.limit(limit) || [];
|
||||
// const foundGames = await db.select({
|
||||
// id: games.id,
|
||||
// name: games.name,
|
||||
// slug: games.slug,
|
||||
// thumb_url: games.thumb_url
|
||||
// })
|
||||
// .from(games)
|
||||
// .where(sql`to_tsvector('simple', ${games.name}) || to_tsvector('simple', ${games.slug}) @@ to_tsquery('simple', ${q})`)
|
||||
// .orderBy(sql`${orderBy} ${order}`).offset(skip).limit(limit) || [];
|
||||
if (foundGames.length === 0) {
|
||||
error(404, { message: 'No games found' });
|
||||
}
|
||||
|
|
@ -54,3 +69,20 @@ export const GET = async ({ url, locals }) => {
|
|||
return json(foundGames);
|
||||
}
|
||||
};
|
||||
|
||||
type OrderDirection = 'asc' | 'desc';
|
||||
|
||||
const getOrderDirection = (direction: OrderDirection) => {
|
||||
return direction === 'asc' ? asc: desc;
|
||||
};
|
||||
|
||||
const getOrderBy = (orderBy: string) => {
|
||||
switch (orderBy) {
|
||||
case 'name':
|
||||
return games.name;
|
||||
case 'slug':
|
||||
return games.slug;
|
||||
default:
|
||||
return games.slug;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
import { customType } from 'drizzle-orm/pg-core';
|
||||
import {sql} from "drizzle-orm";
|
||||
|
||||
function genExpWithWeights(input: string[]) {
|
||||
const columnExpressions = input.map((column, index) => {
|
||||
const weight = String.fromCharCode(index + 65);
|
||||
return `setweight(to_tsvector('english', coalesce(${column}, '')), '${weight}')`;
|
||||
return sql`setweight(to_tsvector('english', coalesce(${column}, '')), '${weight}')`;
|
||||
});
|
||||
|
||||
return `tsvector GENERATED ALWAYS AS (${columnExpressions.join(' || ')}) STORED`;
|
||||
return sql`tsvector GENERATED ALWAYS AS (${columnExpressions.join(' || ')}) STORED`;
|
||||
}
|
||||
|
||||
export const tsvector = customType<{
|
||||
|
|
@ -18,9 +19,9 @@ export const tsvector = customType<{
|
|||
const sources = config.sources.join(" || ' ' || ");
|
||||
return config.weighted
|
||||
? genExpWithWeights(config.sources)
|
||||
: `tsvector generated always as (to_tsvector('english', ${sources})) stored`;
|
||||
: sql`tsvector generated always as (to_tsvector('english', ${sources})) stored`;
|
||||
} else {
|
||||
return `tsvector`;
|
||||
return sql`tsvector`;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue