Skip to main content

myko/search/
entity_search.rs

1//! EntitySearch report for full-text search across entities.
2//!
3//! This report searches for entities matching a query string and returns the matching IDs.
4//!
5//! # Example
6//!
7//! ```rust,no_run
8//! use myko::entities::server::Server;
9//! use myko::search::EntitySearch;
10//!
11//! // Type-safe constructor with default limit (100)
12//! let search = EntitySearch::for_type::<Server>("audio mixer");
13//!
14//! // With custom limit
15//! let _search = EntitySearch::for_type_with_limit::<Server>("audio mixer", 50);
16//! let _ = search;
17//! ```
18//!
19
20use std::sync::Arc;
21
22use crate::{
23    item::Eventable,
24    report::{ReportContext, ReportHandler},
25};
26
27/// Result of an entity search.
28#[myko_macros::myko_report_output]
29pub struct EntitySearchResult {
30    /// IDs of entities matching the search query
31    pub ids: Vec<Arc<str>>,
32}
33
34/// Search for entities by full-text query.
35///
36/// Returns matching entity IDs up to the specified limit.
37/// If the entity type is not indexed for search, returns an empty result.
38#[myko_macros::myko_report(EntitySearchResult)]
39pub struct EntitySearch {
40    /// Entity type to search (e.g., "Target", "Scene")
41    pub entity_type: String,
42    /// Search query string
43    pub query: String,
44    /// Maximum number of results to return (default: 100)
45    #[serde(default = "default_limit")]
46    pub limit: usize,
47}
48
49fn default_limit() -> usize {
50    100
51}
52
53impl EntitySearch {
54    /// Create a new EntitySearch for a specific entity type with default limit (100).
55    ///
56    /// # Example
57    ///
58    /// ```rust,no_run
59    /// use myko::entities::server::Server;
60    /// use myko::search::EntitySearch;
61    ///
62    /// let search = EntitySearch::for_type::<Server>("audio mixer");
63    /// let _ = search;
64    /// ```
65    pub fn for_type<T: Eventable>(query: &str) -> Self {
66        Self::for_type_with_limit::<T>(query, 100)
67    }
68
69    /// Create a new EntitySearch for a specific entity type with custom limit.
70    ///
71    /// # Example
72    ///
73    /// ```rust,no_run
74    /// use myko::entities::server::Server;
75    /// use myko::search::EntitySearch;
76    ///
77    /// let search = EntitySearch::for_type_with_limit::<Server>("audio mixer", 50);
78    /// let _ = search;
79    /// ```
80    pub fn for_type_with_limit<T: Eventable>(query: &str, limit: usize) -> Self {
81        Self {
82            entity_type: T::ENTITY_NAME_STATIC.to_string(),
83            query: query.to_string(),
84            limit,
85        }
86    }
87}
88
89impl ReportHandler for EntitySearch {
90    type Output = EntitySearchResult;
91
92    fn compute(&self, ctx: ReportContext) -> impl hyphae::MaterializeDefinite<Arc<Self::Output>> {
93        // Perform search via ReportContext (sync call)
94        let ids = ctx.search(&self.entity_type, &self.query, self.limit);
95
96        // Create an immutable cell with the search result
97        // Note: This report returns a single result and doesn't update reactively.
98        // For reactive search, you would need to subscribe to entity changes.
99        hyphae::Cell::new(Arc::new(EntitySearchResult { ids })).lock()
100    }
101}