diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php new file mode 100644 index 0000000..0b3b464 --- /dev/null +++ b/app/Http/Controllers/SearchController.php @@ -0,0 +1,83 @@ +client = new Client([ + 'api_key' => '', + 'nodes' => [ + [ + 'host' => env('TYPESENSE_CONNECTION'), + 'port' => '8108', + 'protocol' => 'http', + ], + ], + ]); + } + + + private function createEventsCollection() + { + try { + $collections = $this->client->collections->retrieve(); + + if (!in_array('events', array_column($collections, 'name'))) { + $this->client->collections->create([ + 'name' => 'events', + 'fields' => [ + ['name' => 'name', 'type' => 'string'], + ['name' => 'description', 'type' => 'string'], + ], + ]); + } + } catch (Exception $e) { + throw new Exception("Error while creating the events collection : " . $e->getMessage()); + } + } + + private function indexEvents() + { + try { + $events = Events::all(); + + foreach ($events as $event) { + + $this->client->collections['events']->documents->upsert([ + 'id' => (string) $event->id, + 'name' => $event->name, + 'description' => $event->description, + ]); + } + } catch (Exception $e) { + throw new Exception("Error while indexing events : " . $e->getMessage()); + } + } + + public function searchEvents(Request $request) + { + try { + $this->createEventsCollection(); + $this->indexEvents(); + $query = $request->input('query', ''); + + $searchResults = $this->client->collections['events']->documents->search([ + 'q' => $query, + 'query_by' => 'name,description', + ]); + + return response()->json($searchResults); + } catch (Exception $e) { + return response()->json(['error' => $e->getMessage()], 500); + } + } +} diff --git a/composer.json b/composer.json index b8fdc46..849146c 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ "laravel/framework": "^12.0", "laravel/sanctum": "^4.0", "laravel/tinker": "^2.10.1", + "typesense/typesense-php": "*", "propaganistas/laravel-phone": "^6.0" }, "require-dev": { diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 0693abc..f589968 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -36,8 +36,19 @@ services: volumes: - dbdata:/var/lib/mysql + + typesense: + image: typesense/typesense:29.0 + restart: on-failure + ports: + - "8108:8108" + volumes: + - typesense-data:/data + command: '--data-dir /data --api-key= --enable-cors' + volumes: dbdata: + typesense-data: networks: default: diff --git a/routes/events.php b/routes/events.php index 1cf3184..8ad3ab3 100644 --- a/routes/events.php +++ b/routes/events.php @@ -1,6 +1,7 @@ get('/events', [EventsController::cl Route::middleware(['web', 'auth:sanctum'])->delete('/events/{id}', [EventsController::class, "delete"]); -Route::middleware(['web', 'auth:sanctum'])->get('/events/{id}', [EventsController::class, "getEvent"]); +Route::middleware(['web', 'auth:sanctum'])->get('/events/search', [SearchController::class, "searchEvents"]); + +Route::middleware(['web', 'auth:sanctum'])->get('/events/{id}', [EventsController::class, "getEvent"]); \ No newline at end of file diff --git a/tests/Events/Search events.bru b/tests/Events/Search events.bru new file mode 100644 index 0000000..be93c80 --- /dev/null +++ b/tests/Events/Search events.bru @@ -0,0 +1,19 @@ +meta { + name: Search events + type: http + seq: 7 +} + +get { + url: {{url}}/api/events/search?query=vile + body: none + auth: inherit +} + +params:query { + query: vile +} + +settings { + encodeUrl: true +}