Skip to main content

systemprompt_content/services/search/
mod.rs

1use crate::error::ContentError;
2use crate::models::{SearchRequest, SearchResponse, SearchResult};
3use crate::repository::{ContentRepository, SearchRepository};
4use systemprompt_database::DbPool;
5use systemprompt_identifiers::CategoryId;
6
7const DEFAULT_SEARCH_LIMIT: i64 = 10;
8
9#[derive(Debug)]
10pub struct SearchService {
11    search_repo: SearchRepository,
12    content_repo: ContentRepository,
13}
14
15impl SearchService {
16    pub fn new(db: &DbPool) -> Result<Self, ContentError> {
17        Ok(Self {
18            search_repo: SearchRepository::new(db)?,
19            content_repo: ContentRepository::new(db)?,
20        })
21    }
22
23    pub async fn search(&self, request: &SearchRequest) -> Result<SearchResponse, ContentError> {
24        let limit = request.limit.unwrap_or(DEFAULT_SEARCH_LIMIT);
25
26        let results = if let Some(filters) = &request.filters {
27            if let Some(category_id) = &filters.category_id {
28                self.search_repo
29                    .search_by_category(category_id, limit)
30                    .await?
31            } else {
32                vec![]
33            }
34        } else {
35            let content_list = self.content_repo.list_all(limit, 0).await?;
36            content_list
37                .into_iter()
38                .map(Self::content_to_search_result)
39                .collect()
40        };
41
42        Ok(SearchResponse {
43            total: results.len(),
44            results,
45        })
46    }
47
48    pub async fn search_by_category(
49        &self,
50        category_id: &CategoryId,
51        limit: i64,
52    ) -> Result<Vec<SearchResult>, ContentError> {
53        Ok(self
54            .search_repo
55            .search_by_category(category_id, limit)
56            .await?)
57    }
58
59    fn content_to_search_result(content: crate::models::Content) -> SearchResult {
60        SearchResult {
61            id: content.id,
62            title: content.title,
63            slug: content.slug,
64            description: content.description,
65            image: content.image,
66            view_count: 0,
67            source_id: content.source_id,
68            category_id: content.category_id,
69        }
70    }
71}