private IFieldSort SortFromUserInput(FieldSortDescriptor <BusinessElasticModel> f, BusinessSorting sorting)
        {
            switch (sorting)
            {
            case BusinessSorting.HeaderDesc:
                f.Order(SortOrder.Descending);
                f.Field(ff => ff.Header.Suffix("keyword"));
                break;

            case BusinessSorting.HeaderAcs:
                f.Order(SortOrder.Ascending);
                f.Field(ff => ff.Header.Suffix("keyword"));
                break;

            case BusinessSorting.LatestAdded:
                f.Order(SortOrder.Descending);
                f.Field(ff => ff.Created);
                break;

            case BusinessSorting.LatestUpdated:
                f.Order(SortOrder.Descending);
                f.Field(ff => ff.LastUpdated);
                break;

            default:
                f.Field("_score");
                f.Descending();
                break;
            }
            return(f);
        }
        public async Task <BusinessElasticReturnModel> GetBusinesses(
            long randomSeed,
            int from                = 0,
            int size                = 10,
            string query            = null,
            string tags             = null,
            string transactionTags  = null,
            int[] regionIds         = null,
            bool?digital            = null,
            bool openNow            = false,
            BusinessSorting sorting = BusinessSorting.Random,
            string languageCode     = CmsVariable.DefaultLanguageCode)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            ISearchResponse <BusinessElasticModel> response;

            Func <AggregationContainerDescriptor <BusinessElasticModel>, IAggregationContainer> aggregation = a =>
                                                                                                              a.Terms("by_tags", f => f.Field(c => c.Tags.Suffix("keyword")).Size(1000));

            if (sorting == BusinessSorting.Random)
            {
                response = await _client.SearchAsync <BusinessElasticModel>(s => s
                                                                            .RequestConfiguration(r => r.DisableDirectStreaming())
                                                                            .From(from)
                                                                            .Size(size)
                                                                            .Aggregations(aggregation)
                                                                            .Query(oq =>
                                                                                   oq.FunctionScore(fs => fs
                                                                                                    .Query(MainQuery(query, tags, transactionTags, regionIds, digital, openNow, languageCode))
                                                                                                    .Functions(f => f.RandomScore(rs => rs.Seed(randomSeed))))
                                                                                   )
                                                                            );
            }
            else
            {
                response = await _client.SearchAsync <BusinessElasticModel>(s => s
                                                                            .RequestConfiguration(r => r.DisableDirectStreaming())
                                                                            .From(from)
                                                                            .Size(size)
                                                                            .Aggregations(aggregation)
                                                                            .Query(MainQuery(query, tags, transactionTags, regionIds, digital, openNow, languageCode))
                                                                            .Sort(ss => ss.Field(f => SortFromUserInput(f, sorting)))
                                                                            );
            }

            stopwatch.Stop();

            if (!response.IsValid)
            {
                var errorMessage = $"Response invalid when searching businesses in Elasticsearch.";
                _logger.LogError(errorMessage + " {Debug}", response.DebugInformation);
                throw new Exception(errorMessage);
            }

            var logMessage = $"Query:{query}, regionIds:{regionIds}, LanguageCode:{languageCode}, tags:{tags}, digital:{digital}";

            _logger.LogInformation("Search businesses with filter {LogMessage} found {Count} items. Took {ElapsedTime} milliseconds.", logMessage, response.Documents?.Count, stopwatch?.Elapsed.TotalMilliseconds);

            var list = response.Hits.Select(x => new BusinessElasticReturnItemModel
            {
                Business = x.Source,
                Score    = x.Score
            });

            var byTags = response.Aggregations.Terms("by_tags").Buckets.Select(x => new BusinessElasticTagBucketModel
            {
                Key      = x.Key,
                DocCount = x.DocCount ?? 0
            }).ToList();

            return(new BusinessElasticReturnModel
            {
                Items = list.ToList(),
                Total = response.Total,
                TagCounts = byTags
            });
        }