Skip to main content

llm_wiki/ops/
search.rs

1use anyhow::Result;
2
3use crate::engine::EngineState;
4use crate::search;
5
6/// Parameters for the `search` operation.
7pub struct SearchParams<'a> {
8    /// Full-text query string.
9    pub query: &'a str,
10    /// Restrict results to this frontmatter type.
11    pub type_filter: Option<&'a str>,
12    /// When true, omit body excerpts from results.
13    pub no_excerpt: bool,
14    /// Maximum number of results to return.
15    pub top_k: Option<usize>,
16    /// When true, include section index pages in results.
17    pub include_sections: bool,
18    /// When true, search across all mounted wikis.
19    pub cross_wiki: bool,
20}
21
22/// Run a BM25 search against the wiki index.
23pub fn search(
24    engine: &EngineState,
25    wiki_name: &str,
26    params: &SearchParams<'_>,
27) -> Result<search::SearchResult> {
28    let space = engine.space(wiki_name)?;
29    let resolved = space.resolved_config(&engine.config);
30
31    let opts = search::SearchOptions {
32        no_excerpt: params.no_excerpt,
33        include_sections: params.include_sections,
34        top_k: params
35            .top_k
36            .unwrap_or(resolved.defaults.search_top_k as usize),
37        r#type: params.type_filter.map(|s| s.to_string()),
38        facets_top_tags: resolved.defaults.facets_top_tags as usize,
39        search_config: resolved.search.clone(),
40    };
41
42    if params.cross_wiki {
43        let mut wikis = Vec::new();
44        for s in engine.spaces.values() {
45            let searcher = s.index_manager.searcher()?;
46            wikis.push((s.name.clone(), searcher, &s.index_schema));
47        }
48        return search::search_all(params.query, &opts, &wikis);
49    }
50
51    let searcher = space.index_manager.searcher()?;
52    search::search(
53        params.query,
54        &opts,
55        &searcher,
56        wiki_name,
57        &space.index_schema,
58    )
59}
60
61/// Return a paginated listing of wiki pages with optional type/status filters.
62pub fn list(
63    engine: &EngineState,
64    wiki_name: &str,
65    type_filter: Option<&str>,
66    status: Option<&str>,
67    page: usize,
68    page_size: Option<usize>,
69) -> Result<search::PageList> {
70    let space = engine.space(wiki_name)?;
71    let resolved = space.resolved_config(&engine.config);
72
73    let opts = search::ListOptions {
74        r#type: type_filter.map(|s| s.to_string()),
75        status: status.map(|s| s.to_string()),
76        page,
77        page_size: page_size.unwrap_or(resolved.defaults.list_page_size as usize),
78        facets_top_tags: resolved.defaults.facets_top_tags as usize,
79    };
80    let searcher = space.index_manager.searcher()?;
81    search::list(&opts, &searcher, wiki_name, &space.index_schema)
82}