feat: implement full-text search functionality with API integration, add search router and persistence logic, and create related schemas and tests

This commit is contained in:
2025-09-07 12:36:03 +02:00
parent c3539cfc11
commit 69eb225c1e
15 changed files with 409 additions and 2 deletions

View File

@@ -5,6 +5,7 @@ pub mod auth;
pub mod feed;
pub mod friends;
pub mod root;
pub mod search;
pub mod tag;
pub mod thought;
pub mod user;
@@ -30,6 +31,7 @@ pub fn create_router(state: AppState) -> Router {
.nest("/feed", create_feed_router())
.nest("/tags", tag::create_tag_router())
.nest("/friends", friends::create_friends_router())
.nest("/search", search::create_search_router())
.with_state(state)
.layer(cors)
}

View File

@@ -0,0 +1,53 @@
use crate::{error::ApiError, extractor::OptionalAuthUser};
use app::{persistence::search, state::AppState};
use axum::{
extract::{Query, State},
response::IntoResponse,
routing::get,
Json, Router,
};
use models::schemas::{
search::SearchResultsSchema,
thought::{ThoughtListSchema, ThoughtSchema},
user::UserListSchema,
};
use serde::Deserialize;
use utoipa::IntoParams;
#[derive(Deserialize, IntoParams)]
pub struct SearchQuery {
q: String,
}
#[utoipa::path(
get,
path = "",
params(SearchQuery),
responses((status = 200, body = SearchResultsSchema))
)]
async fn search_all(
State(state): State<AppState>,
viewer: OptionalAuthUser,
Query(query): Query<SearchQuery>,
) -> Result<impl IntoResponse, ApiError> {
let viewer_id = viewer.0.map(|u| u.id);
let (users, thoughts) = tokio::try_join!(
search::search_users(&state.conn, &query.q),
search::search_thoughts(&state.conn, &query.q, viewer_id)
)?;
let thought_schemas: Vec<ThoughtSchema> =
thoughts.into_iter().map(ThoughtSchema::from).collect();
let response = SearchResultsSchema {
users: UserListSchema::from(users),
thoughts: ThoughtListSchema::from(thought_schemas),
};
Ok(Json(response))
}
pub fn create_search_router() -> Router<AppState> {
Router::new().route("/", get(search_all))
}