Skip to main content

gqls/search/
mod.rs

1//! The read path: score every record against the query, rank, truncate.
2
3use crate::model::{Kind, SchemaRecord};
4
5pub mod score;
6
7pub struct Hit<'a> {
8    pub record: &'a SchemaRecord,
9    pub score: i64,
10}
11
12/// Fuzzy-search `records` for `query`, optionally restricted to one `kind`.
13pub fn search<'a>(
14    query: &str,
15    records: &'a [SchemaRecord],
16    kind: Option<Kind>,
17    limit: usize,
18) -> Vec<Hit<'a>> {
19    let mut hits: Vec<Hit> = records
20        .iter()
21        .filter(|r| kind.is_none_or(|k| r.kind == k))
22        .filter_map(|r| score::score(query, r).map(|score| Hit { record: r, score }))
23        .collect();
24
25    // highest score first; break ties toward the shorter path (the more
26    // "central" definition — `User` before `AdminUserAuditLogEntry`).
27    hits.sort_by(|a, b| {
28        b.score
29            .cmp(&a.score)
30            .then_with(|| a.record.path.len().cmp(&b.record.path.len()))
31    });
32    hits.truncate(limit);
33    hits
34}