sortBy = SearchSortBy::relevance(); } /** * Set the search query string */ public function query(string $query): self { $this->query = $query; return $this; } /** * Add a filter */ public function filter(string $field, SearchFilter $filter): self { $this->filters[$field] = $filter; return $this; } /** * Add multiple filters at once */ public function filters(array $filters): self { foreach ($filters as $field => $value) { if ($value instanceof SearchFilter) { $this->filters[$field] = $value; } else { $this->filters[$field] = SearchFilter::equals($value); } } return $this; } /** * Add a field boost */ public function boost(string $field, float $boost): self { $this->boosts[$field] = $boost; return $this; } /** * Restrict search to specific fields */ public function fields(array $fields): self { $this->fields = $fields; return $this; } /** * Set fields to highlight */ public function highlight(array $fields): self { $this->highlightFields = $fields; return $this; } /** * Set result limit */ public function limit(int $limit): self { $this->limit = $limit; return $this; } /** * Set result offset for pagination */ public function offset(int $offset): self { $this->offset = $offset; return $this; } /** * Set pagination (page-based) */ public function page(int $page, int $perPage = 20): self { $this->limit = $perPage; $this->offset = ($page - 1) * $perPage; return $this; } /** * Sort by relevance (default) */ public function sortByRelevance(): self { $this->sortBy = SearchSortBy::relevance(); return $this; } /** * Sort by a field */ public function sortBy(string $field, SearchSortDirection $direction = SearchSortDirection::ASC): self { $this->sortBy = SearchSortBy::field($field, $direction); return $this; } /** * Sort by multiple fields */ public function sortByMultiple(SearchSortField ...$fields): self { $this->sortBy = SearchSortBy::multiple(...$fields); return $this; } /** * Enable/disable highlighting */ public function highlighting(bool $enable): self { $this->enableHighlighting = $enable; return $this; } /** * Enable/disable fuzzy matching */ public function fuzzy(bool $enable): self { $this->enableFuzzyMatching = $enable; return $this; } /** * Set minimum score threshold */ public function minScore(float $minScore): self { $this->minScore = $minScore; return $this; } /** * Common filter shortcuts */ public function where(string $field, mixed $value): self { return $this->filter($field, SearchFilter::equals($value)); } public function whereIn(string $field, array $values): self { return $this->filter($field, SearchFilter::in($values)); } public function whereRange(string $field, mixed $min, mixed $max): self { return $this->filter($field, SearchFilter::range($min, $max)); } public function whereGreaterThan(string $field, mixed $value): self { return $this->filter($field, SearchFilter::greaterThan($value)); } public function whereLessThan(string $field, mixed $value): self { return $this->filter($field, SearchFilter::lessThan($value)); } public function whereContains(string $field, string $value): self { return $this->filter($field, SearchFilter::contains($value)); } public function whereStartsWith(string $field, string $value): self { return $this->filter($field, SearchFilter::startsWith($value)); } /** * Build and return the search query */ public function build(): SearchQuery { return new SearchQuery( entityType: $this->entityType, query: $this->query, filters: $this->filters, boosts: $this->boosts, fields: $this->fields, highlightFields: $this->highlightFields, limit: $this->limit, offset: $this->offset, sortBy: $this->sortBy, enableHighlighting: $this->enableHighlighting, enableFuzzyMatching: $this->enableFuzzyMatching, minScore: $this->minScore ); } /** * Build and execute the search query */ public function search(): SearchResult { return $this->engine->search($this->build()); } /** * Execute search and return only the first result */ public function first(): ?SearchHit { $result = $this->limit(1)->search(); return $result->hits[0] ?? null; } /** * Count total results without retrieving them */ public function count(): int { $result = $this->limit(0)->search(); return $result->total; } }