tercul-backend/internal/app/search/bleve_service.go
Damir Mukimov 0f25c8645c
Add Bleve search integration with hybrid search capabilities
- Add Bleve client for keyword search functionality
- Integrate Bleve service into application builder
- Add BleveIndexPath configuration
- Update domain mappings for proper indexing
- Add comprehensive documentation and tests
2025-11-27 03:40:48 +01:00

96 lines
2.6 KiB
Go

package search
import (
"context"
"tercul/internal/domain"
"tercul/internal/platform/search"
)
// BleveSearchService provides keyword and exact-match search capabilities
// Complements Weaviate's vector/semantic search with traditional full-text search
type BleveSearchService interface {
IndexTranslation(ctx context.Context, translation domain.Translation) error
IndexAllTranslations(ctx context.Context) error
SearchTranslations(ctx context.Context, query string, filters map[string]string, limit int) ([]TranslationSearchResult, error)
}
type TranslationSearchResult struct {
ID uint
Score float64
Title string
Content string
Language string
TranslatableID uint
TranslatableType string
}
type bleveSearchService struct {
translationRepo domain.TranslationRepository
}
func NewBleveSearchService(translationRepo domain.TranslationRepository) BleveSearchService {
return &bleveSearchService{
translationRepo: translationRepo,
}
}
func (s *bleveSearchService) IndexTranslation(ctx context.Context, translation domain.Translation) error {
return search.BleveClient.AddTranslation(translation)
}
func (s *bleveSearchService) IndexAllTranslations(ctx context.Context) error {
// Get all translations from the database and index them
translations, err := s.translationRepo.ListAll(ctx)
if err != nil {
return err
}
for _, translation := range translations {
if err := search.BleveClient.AddTranslation(translation); err != nil {
return err
}
}
return nil
}
func (s *bleveSearchService) SearchTranslations(ctx context.Context, query string, filters map[string]string, limit int) ([]TranslationSearchResult, error) {
results, err := search.BleveClient.Search(query, filters, limit)
if err != nil {
return nil, err
}
var searchResults []TranslationSearchResult
for _, hit := range results.Hits {
// Extract fields from the hit
fields := hit.Fields
result := TranslationSearchResult{
Score: hit.Score,
}
// Safely extract fields with type assertions
if id, ok := fields["id"].(float64); ok {
result.ID = uint(id)
}
if title, ok := fields["title"].(string); ok {
result.Title = title
}
if content, ok := fields["content"].(string); ok {
result.Content = content
}
if language, ok := fields["language"].(string); ok {
result.Language = language
}
if translatableID, ok := fields["translatable_id"].(float64); ok {
result.TranslatableID = uint(translatableID)
}
if translatableType, ok := fields["translatable_type"].(string); ok {
result.TranslatableType = translatableType
}
searchResults = append(searchResults, result)
}
return searchResults, nil
}