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 }