62 lines
1.7 KiB
Go
62 lines
1.7 KiB
Go
package search
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"gorm.io/gorm"
|
|
"senlinai-agent/backend/internal/domain"
|
|
)
|
|
|
|
type Service struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
type Result struct {
|
|
Type string `json:"type"`
|
|
ID uint `json:"id"`
|
|
ProjectID uint `json:"project_id"`
|
|
Title string `json:"title"`
|
|
Snippet string `json:"snippet"`
|
|
}
|
|
|
|
func NewService(database *gorm.DB) *Service {
|
|
return &Service{db: database}
|
|
}
|
|
|
|
func (s *Service) Search(userID uint, query string) ([]Result, error) {
|
|
query = strings.TrimSpace(query)
|
|
if query == "" {
|
|
return []Result{}, nil
|
|
}
|
|
if s.db.Dialector.Name() == "postgres" {
|
|
return s.searchPostgres(userID, query)
|
|
}
|
|
|
|
var notes []domain.Note
|
|
if err := s.db.Joins("JOIN projects ON projects.id = notes.project_id").
|
|
Where("projects.owner_id = ? AND (notes.title LIKE ? OR notes.markdown LIKE ?)", userID, "%"+query+"%", "%"+query+"%").
|
|
Find(¬es).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
results := make([]Result, 0, len(notes))
|
|
for _, note := range notes {
|
|
results = append(results, Result{Type: "note", ID: note.ID, ProjectID: note.ProjectID, Title: note.Title, Snippet: note.Markdown})
|
|
}
|
|
return results, nil
|
|
}
|
|
|
|
func (s *Service) searchPostgres(userID uint, query string) ([]Result, error) {
|
|
var results []Result
|
|
err := s.db.Raw(`
|
|
SELECT 'note' AS type, notes.id, notes.project_id, notes.title, notes.markdown AS snippet
|
|
FROM notes
|
|
JOIN projects ON projects.id = notes.project_id
|
|
WHERE projects.owner_id = ?
|
|
AND to_tsvector('simple', coalesce(notes.title, '') || ' ' || coalesce(notes.markdown, ''))
|
|
@@ plainto_tsquery('simple', ?)
|
|
ORDER BY notes.updated_at DESC
|
|
LIMIT 50
|
|
`, userID, query).Scan(&results).Error
|
|
return results, err
|
|
}
|