diff --git a/bun.lockb b/bun.lockb deleted file mode 100755 index 10a4490e6fafd56fcb781b598b737b0f6840c33c..0000000000000000000000000000000000000000 Binary files a/bun.lockb and /dev/null differ diff --git a/package.json b/package.json index 0ea01d68095bc65ef90caa35733c53f4dd98dd0c..b0c9784abaccc0bdc3367c974ba029da977beec6 100644 --- a/package.json +++ b/package.json @@ -10,12 +10,13 @@ }, "dependencies": { "@aws-sdk/client-s3": "^3.750.0", + "@elastic/elasticsearch": "^8.17.0", "@hono/swagger-ui": "^0.5.0", "@hono/zod-openapi": "^0.18.3", - "@elastic/elasticsearch": "^8.17.0", "@hono/zod-validator": "^0.2.2", "@scalar/hono-api-reference": "^0.8.0", "archiver": "^7.0.1", + "bun": "1.2.10", "dotenv": "^16.4.5", "dotenv-expand": "^11.0.6", "drizzle-orm": "^0.31.2", diff --git a/src/db/repo/search.repo.ts b/src/db/repo/search.repo.ts index 210de3505446d2a9ff8e9e67ca51e9d4829e59e3..b8e10480497b5319a805c5abf10829d70cbb99dd 100644 --- a/src/db/repo/search.repo.ts +++ b/src/db/repo/search.repo.ts @@ -83,7 +83,7 @@ export class SearchRepo { created_at: sql`users.created_at`, is_active: sql`users.is_active`, score: sql`usst.score`, - likes_received: sql`usst.likes_received`, + likes: sql`usst.likes_received`, followers: sql`usst.followers`, approved_resources: sql`usst.approved_resources`, }) @@ -128,7 +128,7 @@ export class SearchRepo { downloads: sql`colst.downloads`, likes: sql`colst.likes`, shares: sql`colst.shares`, - follows: sql`colst.follows`, + followers: sql`colst.follows`, }) .from(sql`collections col`) .leftJoin(sql`users`, sql`users.id = col.user_id`) diff --git a/src/db/schema/search.schema.ts b/src/db/schema/search.schema.ts index d385eeea9161c4aceab60d486b3fcb5346c7b915..8582ac8cf4f86671e092ed7655feb3a9c3c6e45a 100644 --- a/src/db/schema/search.schema.ts +++ b/src/db/schema/search.schema.ts @@ -1,5 +1,4 @@ import { z } from "zod"; -import { resourceEnumSchema } from '../schema/resource-enum.schema' export const resourceIndexSchema = z.object({ id: z.number(), @@ -13,7 +12,7 @@ export const resourceIndexSchema = z.object({ subjects: z.string().nullable(), license: z.string(), object_type: z.string(), - state: resourceEnumSchema, + state: z.number(), user: z.string(), views: z.number(), downloads: z.number(), @@ -24,7 +23,7 @@ export const resourceIndexSchema = z.object({ }); export const userIndexSchema = z.object({ - id: z.number(), + id: z.number(), name: z.string(), username: z.string(), description: z.string().nullable(), @@ -33,7 +32,7 @@ export const userIndexSchema = z.object({ created_at: z.string(), is_active: z.boolean(), score: z.number(), - likes_received: z.number(), + likes: z.number(), followers: z.number(), approved_resources: z.number() }); @@ -49,7 +48,7 @@ export const collectionIndexSchema = z.object({ downloads: z.number(), likes: z.number(), shares: z.number(), - follows: z.number() + followers: z.number() }); // export type LearningObjectIndex = z.infer<typeof learningObjectIndexSchema>; diff --git a/src/routes/search.route.ts b/src/routes/search.route.ts index a30fe330f02d96f45c945232fe5d32cb3d67fca0..c0f9a0bcc1eda761776693ba2d8078fbba5eb701 100644 --- a/src/routes/search.route.ts +++ b/src/routes/search.route.ts @@ -21,7 +21,7 @@ export const searchRouter = new Hono() try { const { query } = c.req.valid('query'); - const results = await searchService.searchIndex(query, {}); + const results = await searchService.searchIndex(query); return c.json({ results }); } catch (e) { diff --git a/src/routes/user.route.ts b/src/routes/user.route.ts index e624f1e02d1611ff87acaa4480568c5e8c5a3285..8c5523ce7f833f76caf1524baaeab61b314e4ef4 100644 --- a/src/routes/user.route.ts +++ b/src/routes/user.route.ts @@ -219,6 +219,8 @@ export const userRouter = honoWithJwt() await service.update(input) ) + await searchService.indexUser(user.id) + return c.json({ user }) } catch (e) { diff --git a/src/services/search.service.ts b/src/services/search.service.ts index 5991e1fc8a32b8ff446097a45d78d7d95d2ea417..3351cb7039306809ffa41e4ec146091d28b0900f 100644 --- a/src/services/search.service.ts +++ b/src/services/search.service.ts @@ -3,12 +3,25 @@ import es from '@/search' import env from '@/env' import { SearchRepo } from "@/db/repo/search.repo"; -type ExactFilterFields = { +export type ExactFilterFields = { language?: string; objectType?: string; institution?: string; + state?: number; }; +export type SortableFilterFields = { + created_at?: string; + views?: number; + downloads?: number; + likes?: number; + shares?: number; + score?: number; + comments?: number; + followers?: number; + approved_resources?: number; +} + @Service() export class SearchService { @Inject('ElasticSearchClient') @@ -81,7 +94,7 @@ export class SearchService { downloads: document.downloads, likes: document.likes, shares: document.shares, - follows: document.follows + followers: document.followers, }, }); @@ -113,7 +126,7 @@ export class SearchService { created_at: document.created_at, is_active: document.is_active, score: document.score, - likes_received: document.likes_received, + likes: document.likes, followers: document.followers, approved_resources: document.approved_resources }, @@ -133,25 +146,31 @@ export class SearchService { // page_size: tamanho da página async searchIndex( query: string, - filters: Partial<ExactFilterFields>, - sortBy?: 'created_at', + filters: Partial<ExactFilterFields> = {}, + sortBy: Partial<SortableFilterFields> = {}, + // sortBy?: 'created_at', sortOrder: 'asc' | 'desc' = 'desc', index: string[] = [env.ELASTIC_INDEX_USERS, env.ELASTIC_INDEX_COLLECTIONS, env.ELASTIC_INDEX_RESOURCES], offset: number = 0, page_size: number = 1000 ) { - const filterClauses = Object.entries(filters) + const userFilters = Object.entries(filters) .filter(([, value]) => value !== undefined) - .map(([key, value]) => ({ - term: { [key]: value }, - })); + .map(([key, value]) => { + if (Array.isArray(value)) { + return { terms: { [key]: value } }; + } else { + return { term: { [key]: value } }; + } + }); let sort: Array<{ [key: string]: { order: 'asc' | 'desc' } }> = []; - if (sortBy) { + if (sortBy && Object.keys(sortBy).length > 0) { + const sortField = Object.keys(sortBy)[0]; sort = [ { - [sortBy]: { + [sortField]: { order: sortOrder, }, }, @@ -174,7 +193,6 @@ export class SearchService { 'author', 'description', 'link', - 'fileFormats', 'educational_stages', 'languages', 'subjects', @@ -185,9 +203,9 @@ export class SearchService { 'roles', 'institution', 'city', - 'views', - 'downloads', - 'likes', + // 'views', + // 'downloads', + // 'likes', 'shares', 'score', 'comments', @@ -195,7 +213,7 @@ export class SearchService { }, }, ], - filter: filterClauses, + filter: userFilters, }, }, sort: sort.length > 0 ? sort : undefined,