# Searchers Service Kind

## Overview

Searchers are entity-specific services responsible for providing search functionality across domain models. They create searchable indices, handle search queries with filtering and scoping, and generate search result presentations for UI components.

## Architecture

### Core Components

**Base Searcher Library** (`src/lib/searcher/`)
- `Searcher` struct: Core search engine with indexing and query capabilities
- `SearchValue`: Individual search result item with metadata
- `ScopeItem`: Scope-based filtering mechanism
- `Mod`: Search modification object for query parameters

**Entity-Specific Searchers** (`src/srv/searchers/`)
- Each domain model has its own dedicated searcher (e.g., `GardenSearcher`, `UserSearcher`)
- All searchers follow the same interface pattern and method conventions
- Integrated with Fetchers, Stringers, Presenters, and Urlers

### Key Structures

#### SearchValue
Represents a searchable entity with metadata:
- **Id**: Unique search identifier (prefixed with model type)
- **Text**: Searchable text content (lowercased)
- **ModelId**: Original entity ID
- **Model**: Entity type identifier
- **Url**: Navigation URL for the entity
- **Scope**: Array of scope items for filtered search
- **Index**: Position in search results

#### ScopeItem
Enables scoped/filtered searching:
- **Name**: Scope category name
- **Value**: Scope filter value
- **Text**: Human-readable scope description

## Standard Methods

Every entity searcher implements these standard methods:

### Search Index Methods
```go
SearchValues(ctx) []searcher.SearchValue
```
- Generate searchable values for all entities of this type
- Convert entities to searchable format with URLs and text
- Include scope information for filtered searching

### Search Result Methods
```go
GetSearchItem(ctx, value) goc.HTML
```
- Generate HTML presentation for a search result
- Load entity data and format for display
- Use presenters to create consistent search result UI

### Internal Methods
```go
getScope(ctx, entity) []*searcher.ScopeItem
```
- Generate scope items for entity-specific filtering
- Enable contextual search within entity relationships
- Return empty slice if no scoping is needed

## Usage Examples

### Search Index Generation
```go
// Generate search values for gardens
values := gardenSearcher.SearchValues(ctx)
// Returns SearchValue objects with searchable text and metadata
```

### Search Result Presentation
```go
// Get HTML for specific search result
searchValue := searcher.SearchValue{ModelId: "123", Model: "garden"}
html := gardenSearcher.GetSearchItem(ctx, searchValue)
```

### Full Search Workflow
```go
// Index all searchable content
indexValues := searchers.Indexing(ctx)  // Aggregates all entity searchers

// Perform search with query
results := searcher.SearchValues(ctx, "text", "garden search", nil)

// Generate HTML for results
items := searchers.GetSearchItems(ctx, results)
```

## Search Indexing Process

### 1. Entity Retrieval
```go
entities := this.GardenFetcher.MustFindAll(ctx, nil)
```

### 2. Search Value Creation
```go
for _, entity := range entities {
    value := searcher.SearchValue{
        Id:      "garden_" + entity.Id,
        Text:    strings.ToLower(this.GardenStringer.MustToString(entity)),
        ModelId: entity.Id,
        Model:   "garden",
        Url:     this.AppUrler.ShowGarden(entity.Id),
        Scope:   this.getScope(ctx, entity),
    }
    values = append(values, value)
}
```

## Search Query Processing

The base `Searcher` supports various query modifiers:

### Model-Specific Search
```
":garden my search text"  // Search only within garden entities
```

### Text Matching
- Case-insensitive substring matching
- Supports multi-word queries
- Results limited to 10 items by default

### Scoped Search
- Filter results based on scope items
- Enable contextual search within relationships
- Support hierarchical filtering

## Integration with Framework

### With Fetchers
```go
entities := this.GardenFetcher.MustFindAll(ctx, nil)
entity := this.GardenFetcher.ShallFindOneById(ctx, id, nil)
```

### With Stringers
```go
Text: strings.ToLower(this.GardenStringer.MustToString(entity))
```

### With Presenters
```go
return this.GardenPresenter.Search(ctx, &value, entity)
```

### With Urlers
```go
Url: this.AppUrler.ShowGarden(entity.Id)
```

## Global Search Coordination

The `Searchers` struct coordinates search across all entities:

### Index Aggregation
```go
func (this *Searchers) Indexing(ctx context.Context) []searcher.SearchValue {
    var values []searcher.SearchValue
    values = append(values, this.GardenSearcher.SearchValues(ctx)...)
    values = append(values, this.UserSearcher.SearchValues(ctx)...)
    // ... all other searchers
    return values
}
```

### Result Presentation
```go
func (this *Searchers) GetSearchItem(ctx context.Context, value searcher.SearchValue) goc.HTML {
    switch value.Model {
    case "garden":
        return this.GardenSearcher.GetSearchItem(ctx, value)
    case "user":
        return this.UserSearcher.GetSearchItem(ctx, value)
    }
}
```

## Search Performance

### Indexing Strategy
- In-memory search index for fast queries
- Lazy loading with indexing state management
- Background indexing to prevent blocking

### Query Optimization
- Result limiting (10 items max by default)
- Early termination on match limits
- Efficient string matching with case normalization

## Search Features

### Query Syntax
- **Plain text**: `"garden name"` - Basic text search
- **Model filter**: `":garden vegetable"` - Search within specific entity type
- **Multi-word**: `"my garden vegetables"` - Match all words

### Result Metadata
- Direct navigation URLs for each result
- Entity type identification for UI styling
- Scope information for contextual filtering
- Consistent HTML presentation across entity types