flamingo.me/flamingo-commerce/v3@v3.11.0/product/application/searchService.go (about)

     1  package application
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/url"
     7  
     8  	"flamingo.me/flamingo/v3/framework/flamingo"
     9  	"flamingo.me/flamingo/v3/framework/web"
    10  
    11  	"flamingo.me/flamingo-commerce/v3/product/domain"
    12  	"flamingo.me/flamingo-commerce/v3/search/application"
    13  	searchdomain "flamingo.me/flamingo-commerce/v3/search/domain"
    14  	"flamingo.me/flamingo-commerce/v3/search/utils"
    15  )
    16  
    17  type (
    18  	// ProductSearchService - Application service that offers a more explicit way to search for  product results - on top of the domain.ProductSearchService
    19  	ProductSearchService struct {
    20  		searchService         domain.SearchService
    21  		paginationInfoFactory *utils.PaginationInfoFactory
    22  		defaultPageSize       float64
    23  		logger                flamingo.Logger
    24  	}
    25  
    26  	// SearchResult - much like the corresponding struct in search package, just that instead "Hits" we have a list of matching Products
    27  	SearchResult struct {
    28  		Suggestions    []searchdomain.Suggestion
    29  		Products       []domain.BasicProduct
    30  		SearchMeta     searchdomain.SearchMeta
    31  		Facets         searchdomain.FacetCollection
    32  		PaginationInfo utils.PaginationInfo
    33  		Promotions     []searchdomain.Promotion
    34  		Actions        []searchdomain.Action
    35  	}
    36  )
    37  
    38  // Inject dependencies
    39  func (s *ProductSearchService) Inject(
    40  	searchService domain.SearchService,
    41  	paginationInfoFactory *utils.PaginationInfoFactory,
    42  	logger flamingo.Logger,
    43  	cfg *struct {
    44  		DefaultPageSize float64 `inject:"config:commerce.product.pagination.defaultPageSize,optional"`
    45  	},
    46  ) *ProductSearchService {
    47  	s.searchService = searchService
    48  	s.paginationInfoFactory = paginationInfoFactory
    49  	s.logger = logger.
    50  		WithField(flamingo.LogKeyModule, "product").
    51  		WithField(flamingo.LogKeyCategory, "application.ProductSearchService")
    52  	if cfg != nil {
    53  		s.defaultPageSize = cfg.DefaultPageSize
    54  	}
    55  
    56  	return s
    57  }
    58  
    59  // Find return SearchResult with matched products - based on given input
    60  func (s *ProductSearchService) Find(ctx context.Context, searchRequest *application.SearchRequest) (*SearchResult, error) {
    61  	var currentURL *url.URL
    62  	request := web.RequestFromContext(ctx)
    63  	if request == nil {
    64  		currentURL = nil
    65  	} else {
    66  		currentURL = request.Request().URL
    67  	}
    68  
    69  	if searchRequest == nil {
    70  		searchRequest = &application.SearchRequest{}
    71  	}
    72  	// pageSize can either be set in the request, or we use the configured default or if nothing set we rely on the ProductSearchService later
    73  	pageSize := searchRequest.PageSize
    74  	if pageSize == 0 {
    75  		pageSize = int(s.defaultPageSize)
    76  	}
    77  
    78  	result, err := s.searchService.Search(ctx, application.BuildFilters(*searchRequest, pageSize)...)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  
    83  	if searchRequest.PaginationConfig == nil {
    84  		searchRequest.PaginationConfig = s.paginationInfoFactory.DefaultConfig
    85  	}
    86  
    87  	if pageSize != 0 {
    88  		if err := result.SearchMeta.ValidatePageSize(pageSize); err != nil {
    89  			err = fmt.Errorf("the Searchservice seems to ignore pageSize filter, %w", err)
    90  			s.logger.WithContext(ctx).WithField(flamingo.LogKeySubCategory, "Find").Warn(err)
    91  		}
    92  	}
    93  	paginationInfo := utils.BuildWith(utils.CurrentResultInfos{
    94  		LastPage:   result.SearchMeta.NumPages,
    95  		TotalHits:  result.SearchMeta.NumResults,
    96  		PageSize:   searchRequest.PageSize,
    97  		ActivePage: result.SearchMeta.Page,
    98  	}, *searchRequest.PaginationConfig, currentURL)
    99  
   100  	return &SearchResult{
   101  		SearchMeta:     result.SearchMeta,
   102  		Facets:         result.Facets,
   103  		Suggestions:    result.Suggestion,
   104  		Products:       result.Hits,
   105  		PaginationInfo: paginationInfo,
   106  		Promotions:     result.Promotions,
   107  		Actions:        result.Actions,
   108  	}, nil
   109  }
   110  
   111  // FindBy return SearchResult with matched products filtered by the given attribute - based on given input
   112  func (s *ProductSearchService) FindBy(ctx context.Context, attributeCode string, values []string, searchRequest *application.SearchRequest) (*SearchResult, error) {
   113  	var currentURL *url.URL
   114  	request := web.RequestFromContext(ctx)
   115  	if request == nil {
   116  		currentURL = nil
   117  	} else {
   118  		currentURL = request.Request().URL
   119  	}
   120  
   121  	if searchRequest == nil {
   122  		searchRequest = &application.SearchRequest{}
   123  	}
   124  	// pageSize can either be set in the request, or we use the configured default or if nothing set we rely on the ProductSearchService later
   125  	pageSize := searchRequest.PageSize
   126  	if pageSize == 0 {
   127  		pageSize = int(s.defaultPageSize)
   128  	}
   129  
   130  	result, err := s.searchService.SearchBy(ctx, attributeCode, values, application.BuildFilters(*searchRequest, pageSize)...)
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  
   135  	if searchRequest.PaginationConfig == nil {
   136  		searchRequest.PaginationConfig = s.paginationInfoFactory.DefaultConfig
   137  	}
   138  
   139  	if pageSize != 0 {
   140  		if err := result.SearchMeta.ValidatePageSize(pageSize); err != nil {
   141  			err = fmt.Errorf("the Searchservice seems to ignore pageSize filter, %w", err)
   142  			s.logger.WithContext(ctx).WithField(flamingo.LogKeySubCategory, "FindBy").Warn(err)
   143  		}
   144  	}
   145  	paginationInfo := utils.BuildWith(utils.CurrentResultInfos{
   146  		LastPage:   result.SearchMeta.NumPages,
   147  		TotalHits:  result.SearchMeta.NumResults,
   148  		PageSize:   searchRequest.PageSize,
   149  		ActivePage: result.SearchMeta.Page,
   150  	}, *searchRequest.PaginationConfig, currentURL)
   151  
   152  	return &SearchResult{
   153  		SearchMeta:     result.SearchMeta,
   154  		Facets:         result.Facets,
   155  		Suggestions:    result.Suggestion,
   156  		Products:       result.Hits,
   157  		PaginationInfo: paginationInfo,
   158  		Promotions:     result.Result.Promotions,
   159  		Actions:        result.Actions,
   160  	}, nil
   161  }