Skip to content

Commit

Permalink
Added strict match checkboxes for workshop filter (#772)
Browse files Browse the repository at this point in the history
* Added strict match checkboxes for workshop filter

* Fixed code smels

* Implemented pattern Strategy for workshop

* Refactored code using dependency injection

* Small refactor

* small refactor
  • Loading branch information
Vizary authored Jul 29, 2022
1 parent 9983444 commit ce4e07a
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 51 deletions.
13 changes: 7 additions & 6 deletions OutOfSchool/OutOfSchool.ElasticsearchData/ESWorkshopProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Threading.Tasks;
using Nest;
using OutOfSchool.Common;
using OutOfSchool.Common.Enums;
using OutOfSchool.ElasticsearchData.Enums;
using OutOfSchool.ElasticsearchData.Models;

Expand Down Expand Up @@ -134,14 +133,14 @@ private QueryContainer CreateQueryFromFilter(WorkshopFilterES filter)

ageQuery = new NumericRangeQuery()
{
Field = Infer.Field<WorkshopES>(w => w.MinAge),
LessThanOrEqualTo = filter.MaxAge,
Field = filter.IsAppropriateAge ? Infer.Field<WorkshopES>(w => w.MinAge) : Infer.Field<WorkshopES>(w => w.MaxAge),
GreaterThanOrEqualTo = filter.MinAge,
};

ageQuery &= new NumericRangeQuery()
{
Field = Infer.Field<WorkshopES>(w => w.MaxAge),
GreaterThanOrEqualTo = filter.MinAge,
Field = filter.IsAppropriateAge ? Infer.Field<WorkshopES>(w => w.MaxAge) : Infer.Field<WorkshopES>(w => w.MinAge),
LessThanOrEqualTo = filter.MaxAge,
};

queryContainer &= ageQuery;
Expand Down Expand Up @@ -173,7 +172,9 @@ private QueryContainer CreateQueryFromFilter(WorkshopFilterES filter)
Path = Infer.Field<WorkshopES>(p => p.DateTimeRanges),
Query = new MatchQuery()
{
Field = Infer.Field<WorkshopES>(w => w.DateTimeRanges.First().Workdays),
Field = filter.IsStrictWorkdays
? Infer.Field<WorkshopES>(w => w.DateTimeRanges.First().Workdays.Suffix("keyword"))
: Infer.Field<WorkshopES>(w => w.DateTimeRanges.First().Workdays),
Query = filter.Workdays,
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,8 @@ public class WorkshopFilterES
public decimal Longitude { get; set; } = 0;

public IReadOnlyCollection<WorkshopStatus> Statuses { get; set; } = new List<WorkshopStatus>();

public bool IsAppropriateAge { get; set; } = false;

public bool IsStrictWorkdays { get; set; } = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,8 @@ public class WorkshopFilter : OffsetFilter
public decimal Longitude { get; set; } = 0;

public IReadOnlyCollection<WorkshopStatus> Statuses { get; set; } = new List<WorkshopStatus>();

public bool IsAppropriateAge { get; set; } = false;

public bool IsStrictWorkdays { get; set; } = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,9 @@ private Expression<Func<Workshop, bool>> PredicateBuild(WorkshopFilter filter)

if (filter.MinAge != 0 || filter.MaxAge != 100)
{
predicate = predicate.And(x => x.MinAge <= filter.MaxAge && x.MaxAge >= filter.MinAge);
predicate = filter.IsAppropriateAge
? predicate.And(x => x.MinAge >= filter.MinAge && x.MaxAge <= filter.MaxAge)
: predicate.And(x => x.MinAge <= filter.MaxAge && x.MaxAge >= filter.MinAge);
}

if (filter.WithDisabilityOptions)
Expand All @@ -568,7 +570,9 @@ private Expression<Func<Workshop, bool>> PredicateBuild(WorkshopFilter filter)

if (workdaysBitMask > 0)
{
predicate = predicate.And(x => x.DateTimeRanges.Any(tr => (tr.Workdays & workdaysBitMask) > 0));
predicate = filter.IsStrictWorkdays
? predicate.And(x => x.DateTimeRanges.Any(tr => (tr.Workdays == workdaysBitMask)))
: predicate.And(x => x.DateTimeRanges.Any(tr => (tr.Workdays & workdaysBitMask) > 0));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using OutOfSchool.WebApi.Models;

namespace OutOfSchool.WebApi.Services.Strategies.Interfaces;

public interface IWorkshopStrategy
{
Task<SearchResult<WorkshopCard>> SearchAsync(WorkshopFilter filter);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using OutOfSchool.WebApi.Models;
using OutOfSchool.WebApi.Services.Strategies.Interfaces;

namespace OutOfSchool.WebApi.Services.Strategies.WorkshopStrategies;

public class WorkshopESStrategy : IWorkshopStrategy
{
private readonly IElasticsearchService<WorkshopES, WorkshopFilterES> elasticsearchService;
private readonly ILogger<WorkshopESStrategy> logger;

public WorkshopESStrategy(IElasticsearchService<WorkshopES, WorkshopFilterES> elasticsearchService, ILogger<WorkshopESStrategy> logger)
{
this.elasticsearchService = elasticsearchService ?? throw new ArgumentNullException();
this.logger = logger;
}

public async Task<SearchResult<WorkshopCard>> SearchAsync(WorkshopFilter filter)
{
var result = await elasticsearchService.Search(filter.ToESModel()).ConfigureAwait(false);

if (result.TotalAmount <= 0)
{
logger?.LogInformation($"Result was {result.TotalAmount}");
}

return result.ToSearchResult();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using OutOfSchool.WebApi.Models;
using OutOfSchool.WebApi.Services.Strategies.Interfaces;

namespace OutOfSchool.WebApi.Services.Strategies.WorkshopStrategies;

public class WorkshopServiceStrategy : IWorkshopStrategy
{
private readonly IWorkshopService workshopService;
private readonly ILogger<WorkshopServiceStrategy> logger;

public WorkshopServiceStrategy(IWorkshopService workshopService, ILogger<WorkshopServiceStrategy> logger)
{
this.workshopService = workshopService ?? throw new ArgumentNullException();
this.logger = logger;
}

public async Task<SearchResult<WorkshopCard>> SearchAsync(WorkshopFilter filter)
{
var databaseResult = await workshopService.GetByFilter(filter).ConfigureAwait(false);

if (databaseResult.TotalAmount <= 0)
{
logger?.LogInformation($"Result was {databaseResult.TotalAmount}");
}

return new SearchResult<WorkshopCard>() { TotalAmount = databaseResult.TotalAmount, Entities = databaseResult.Entities };
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,33 @@
using OutOfSchool.WebApi.Enums;
using OutOfSchool.WebApi.Models;
using OutOfSchool.WebApi.Models.Workshop;
using OutOfSchool.WebApi.Services.Strategies.Interfaces;

namespace OutOfSchool.WebApi.Services;

public class WorkshopServicesCombiner : IWorkshopServicesCombiner, INotificationReciever
{
private protected readonly IWorkshopService workshopService; // make it private after removing v2 version
private readonly IElasticsearchService<WorkshopES, WorkshopFilterES> elasticsearchService;
private readonly ILogger<WorkshopServicesCombiner> logger;
private protected readonly IElasticsearchSynchronizationService elasticsearchSynchronizationService; // make it private after removing v2 version
private readonly INotificationService notificationService;
private readonly IEntityRepository<long, Favorite> favoriteRepository;
private readonly IApplicationRepository applicationRepository;
private readonly IWorkshopStrategy workshopStrategy;

public WorkshopServicesCombiner(
IWorkshopService workshopService,
IElasticsearchService<WorkshopES, WorkshopFilterES> elasticsearchService,
ILogger<WorkshopServicesCombiner> logger,
IElasticsearchSynchronizationService elasticsearchSynchronizationService,
INotificationService notificationService,
IEntityRepository<long, Favorite> favoriteRepository,
IApplicationRepository applicationRepository)
IApplicationRepository applicationRepository,
IWorkshopStrategy workshopStrategy)
{
this.workshopService = workshopService;
this.elasticsearchService = elasticsearchService;
this.logger = logger;
this.elasticsearchSynchronizationService = elasticsearchSynchronizationService;
this.notificationService = notificationService;
this.favoriteRepository = favoriteRepository;
this.applicationRepository = applicationRepository;
this.workshopStrategy = workshopStrategy;
}

/// <inheritdoc/>
Expand Down Expand Up @@ -136,22 +134,7 @@ public async Task<SearchResult<WorkshopCard>> GetAll(OffsetFilter offsetFilter)
OrderByField = OrderBy.Id.ToString(),
};

if (elasticsearchService.IsElasticAlive)
{
var result = await elasticsearchService.Search(filter.ToESModel()).ConfigureAwait(false);
if (result.TotalAmount <= 0)
{
logger.LogInformation($"Result was {result.TotalAmount}");
}

return result.ToSearchResult();
}
else
{
var databaseResult = await workshopService.GetByFilter(filter).ConfigureAwait(false);

return new SearchResult<WorkshopCard>() { TotalAmount = databaseResult.TotalAmount, Entities = databaseResult.Entities };
}
return await workshopStrategy.SearchAsync(filter);
}

/// <inheritdoc/>
Expand All @@ -162,22 +145,7 @@ public async Task<SearchResult<WorkshopCard>> GetByFilter(WorkshopFilter filter)
return new SearchResult<WorkshopCard> { TotalAmount = 0, Entities = new List<WorkshopCard>() };
}

if (elasticsearchService.IsElasticAlive)
{
var result = await elasticsearchService.Search(filter.ToESModel()).ConfigureAwait(false);
if (result.TotalAmount <= 0)
{
logger.LogInformation($"Result was {result.TotalAmount}");
}

return result.ToSearchResult();
}
else
{
var databaseResult = await workshopService.GetByFilter(filter).ConfigureAwait(false);

return new SearchResult<WorkshopCard>() { TotalAmount = databaseResult.TotalAmount, Entities = databaseResult.Entities };
}
return await workshopStrategy.SearchAsync(filter);
}

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
using OutOfSchool.Services.Enums;
using OutOfSchool.WebApi.Models;
using OutOfSchool.WebApi.Models.Workshop;
using OutOfSchool.WebApi.Services.Strategies.Interfaces;

namespace OutOfSchool.WebApi.Services;

public class WorkshopServicesCombinerV2 : WorkshopServicesCombiner, IWorkshopServicesCombinerV2
{
public WorkshopServicesCombinerV2(
IWorkshopService workshopService,
IElasticsearchService<WorkshopES, WorkshopFilterES> elasticsearchService,
ILogger<WorkshopServicesCombiner> logger,
IElasticsearchSynchronizationService elasticsearchSynchronizationService,
INotificationService notificationService,
IEntityRepository<long, Favorite> favoriteRepository,
IApplicationRepository applicationRepository)
: base(workshopService, elasticsearchService, logger, elasticsearchSynchronizationService, notificationService, favoriteRepository, applicationRepository)
IApplicationRepository applicationRepository,
IWorkshopStrategy workshopStrategy)
: base(workshopService, elasticsearchSynchronizationService, notificationService, favoriteRepository, applicationRepository, workshopStrategy)
{
}

Expand Down
9 changes: 9 additions & 0 deletions OutOfSchool/OutOfSchool.WebApi/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Text.Json.Serialization;
using OutOfSchool.WebApi.Services.Strategies.Interfaces;
using OutOfSchool.WebApi.Services.Strategies.WorkshopStrategies;

namespace OutOfSchool.WebApi;

Expand Down Expand Up @@ -196,6 +198,13 @@ public static void AddApplicationServices(this WebApplicationBuilder builder)
services.AddTransient<IBlockedProviderParentService, BlockedProviderParentService>();
services.AddTransient<ICodeficatorService, CodeficatorService>();
services.AddTransient<IGRPCCommonService, GRPCCommonService>();
services.AddTransient<IWorkshopStrategy>(sp =>
{
var elasticSearchService = sp.GetRequiredService<IElasticsearchService<WorkshopES, WorkshopFilterES>>();
return elasticSearchService.IsElasticAlive
? new WorkshopESStrategy(elasticSearchService, sp.GetRequiredService<ILogger<WorkshopESStrategy>>())
: new WorkshopServiceStrategy(sp.GetRequiredService<IWorkshopService>(), sp.GetRequiredService<ILogger<WorkshopServiceStrategy>>());
});

// entities repositories
services.AddTransient<IEntityRepository<long, Address>, EntityRepository<long, Address>>();
Expand Down

0 comments on commit ce4e07a

Please sign in to comment.