Files
b2b/app/service/meiliService/meiliService.go

222 lines
6.5 KiB
Go

package meiliService
import (
"fmt"
"regexp"
"strconv"
"strings"
"time"
"git.ma-al.com/goc_daniel/b2b/app/config"
"git.ma-al.com/goc_daniel/b2b/app/repos/productDescriptionRepo"
constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data"
"github.com/meilisearch/meilisearch-go"
)
type MeiliService struct {
productDescriptionRepo productDescriptionRepo.UIProductDescriptionRepo
meiliClient meilisearch.ServiceManager
}
func New() *MeiliService {
client := meilisearch.New(
config.Get().MailiSearch.ServerURL,
meilisearch.WithAPIKey(config.Get().MailiSearch.ApiKey),
)
return &MeiliService{
meiliClient: client,
productDescriptionRepo: productDescriptionRepo.New(),
}
}
// ==================================== FOR TESTING ONLY ====================================
func (s *MeiliService) CreateIndex(id_lang uint) error {
indexName := "meili_products_shop" + strconv.FormatInt(constdata.SHOP_ID, 10) + "_lang" + strconv.FormatInt(int64(id_lang), 10)
products, err := s.productDescriptionRepo.GetMeiliProducts(id_lang)
for i := 0; i < len(products); i++ {
products[i].Description = cleanHTML(products[i].Description)
products[i].DescriptionShort = cleanHTML(products[i].DescriptionShort)
products[i].Usage = cleanHTML(products[i].Usage)
}
primaryKey := "ProductID"
docOptions := &meilisearch.DocumentOptions{
PrimaryKey: &primaryKey,
SkipCreation: false,
}
task, err := s.meiliClient.Index(indexName).AddDocuments(products, docOptions)
if err != nil {
return fmt.Errorf("meili AddDocuments error: %w", err)
}
finishedTask, err := s.meiliClient.WaitForTask(task.TaskUID, 500*time.Millisecond)
fmt.Printf("Task status: %s\n", finishedTask.Status)
fmt.Printf("Task error: %s\n", finishedTask.Error)
filterableAttributes := []interface{}{
"CategoryID",
"CategoryIDs",
}
task, err = s.meiliClient.Index(indexName).UpdateFilterableAttributes(&filterableAttributes)
if err != nil {
return fmt.Errorf("meili AddDocuments error: %w", err)
}
finishedTask, err = s.meiliClient.WaitForTask(task.TaskUID, 500*time.Millisecond)
fmt.Printf("Task status: %s\n", finishedTask.Status)
fmt.Printf("Task error: %s\n", finishedTask.Error)
displayedAttributes := []string{
"ProductID",
"Name",
"EAN13",
"Reference",
"Variations",
"CoverImage",
}
task, err = s.meiliClient.Index(indexName).UpdateDisplayedAttributes(&displayedAttributes)
if err != nil {
return fmt.Errorf("meili AddDocuments error: %w", err)
}
finishedTask, err = s.meiliClient.WaitForTask(task.TaskUID, 500*time.Millisecond)
fmt.Printf("Task status: %s\n", finishedTask.Status)
fmt.Printf("Task error: %s\n", finishedTask.Error)
searchableAttributes := []string{
"Name",
"DescriptionShort",
"Reference",
"EAN13",
"CategoryName",
"Description",
"Usage",
}
task, err = s.meiliClient.Index(indexName).UpdateSearchableAttributes(&searchableAttributes)
if err != nil {
return fmt.Errorf("meili AddDocuments error: %w", err)
}
finishedTask, err = s.meiliClient.WaitForTask(task.TaskUID, 500*time.Millisecond)
fmt.Printf("Task status: %s\n", finishedTask.Status)
fmt.Printf("Task error: %s\n", finishedTask.Error)
return err
}
// ==================================== FOR TESTING ONLY ====================================
func (s *MeiliService) Test(id_lang uint) (meilisearch.SearchResponse, error) {
indexName := "meili_products_shop" + strconv.FormatInt(constdata.SHOP_ID, 10) + "_lang" + strconv.FormatInt(int64(id_lang), 10)
searchReq := &meilisearch.SearchRequest{
Limit: 4,
Facets: []string{
"CategoryID",
},
}
// Perform search
results, err := s.meiliClient.Index(indexName).Search("mat", searchReq)
if err != nil {
fmt.Printf("Meilisearch error: %v\n", err)
return meilisearch.SearchResponse{}, err
}
fmt.Printf("Search results for query 'mat' in %s: %d hits\n", indexName, len(results.Hits))
return *results, nil
}
// Search performs a full-text search on the specified index
func (s *MeiliService) Search(id_lang uint, query string, id_category uint) (meilisearch.SearchResponse, error) {
indexName := "meili_products_shop" + strconv.FormatInt(constdata.SHOP_ID, 10) + "_lang" + strconv.FormatInt(int64(id_lang), 10)
filter_query := "Active = 1"
if id_category != 0 {
// Use CategoryIDs to include products from child categories
filter_query += fmt.Sprintf(" AND CategoryIDs = %d", id_category)
}
searchReq := &meilisearch.SearchRequest{
Limit: 30,
Facets: []string{
"CategoryID",
},
Filter: filter_query,
}
results, err := s.meiliClient.Index(indexName).Search(query, searchReq)
if err != nil {
fmt.Printf("Meilisearch search error: %v\n", err)
return meilisearch.SearchResponse{}, err
}
return *results, nil
}
// HealthCheck checks if Meilisearch is healthy and accessible
func (s *MeiliService) HealthCheck() (*meilisearch.Health, error) {
health, err := s.meiliClient.Health()
if err != nil {
return nil, fmt.Errorf("meilisearch health check failed: %w", err)
}
return health, nil
}
// GetIndexSettings retrieves the current settings for a specific index
func (s *MeiliService) GetIndexSettings(id_lang uint) (map[string]interface{}, error) {
indexName := "meili_products_shop" + strconv.FormatInt(constdata.SHOP_ID, 10) + "_lang" + strconv.FormatInt(int64(id_lang), 10)
index := s.meiliClient.Index(indexName)
result := make(map[string]interface{})
// Get searchable attributes
searchable, err := index.GetSearchableAttributes()
if err == nil {
result["searchableAttributes"] = searchable
}
// Get filterable attributes
filterable, err := index.GetFilterableAttributes()
if err == nil {
result["filterableAttributes"] = filterable
}
// Get displayed attributes
displayed, err := index.GetDisplayedAttributes()
if err == nil {
result["displayedAttributes"] = displayed
}
// Get ranking rules
ranking, err := index.GetRankingRules()
if err == nil {
result["rankingRules"] = ranking
}
// Get distinct attribute
distinct, err := index.GetDistinctAttribute()
if err == nil && distinct != nil {
result["distinctAttribute"] = *distinct
}
// Get typo tolerance
typo, err := index.GetTypoTolerance()
if err == nil {
result["typoTolerance"] = typo
}
return result, nil
}
// remove all tags from HTML text
func cleanHTML(s string) string {
// Simple regex to remove all HTML tags
re := regexp.MustCompile(`<[^>]*>`)
result := re.ReplaceAllString(s, "")
// Replace multiple spaces with single space
result = regexp.MustCompile(`\s+`).ReplaceAllString(result, " ")
return strings.TrimSpace(result)
}