Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/SImpl.SearchModule.Abstraction/Queries/IMultiSearchQuery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using SImpl.CQRS.Queries;
using SImpl.SearchModule.Abstraction.Models;
using SImpl.SearchModule.Abstraction.Results;

namespace SImpl.SearchModule.Abstraction.Queries
{
public interface IMultiSearchQuery : IQuery<IMultiSearchQueryResult>
{
public IDictionary<string, ISearchQuery<IQueryResult>> Queries { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Collections.Generic;
using SImpl.SearchModule.Abstraction.Results;

namespace SImpl.SearchModule.Abstraction.Queries
{
public class MultiSearchQueryResult : IMultiSearchQueryResult
{
public IDictionary<string, IQueryResult> Results { get; set; }
}
public interface IMultiSearchQueryResult
{
public IDictionary<string, IQueryResult> Results { get; set; }
}
}
8 changes: 4 additions & 4 deletions src/SImpl.SearchModule.Abstraction/Queries/ISearchQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ namespace SImpl.SearchModule.Abstraction.Queries
{
public interface ISearchQuery<T> : IDictionary<Occurance, ISearchSubQuery>, ICreatableSearchQuery<Occurance, ISearchSubQuery>, IQuery<T>, ISearchQuery
{
public int Page { get; set; }
public int PageSize { get; set; }
public List<ISortOrderField> SortOrder { get; set; }
public List<IAggregationQuery> FacetQueries { get; set; }
public List<IHighlightQuery> HighlightQueries { get; set; }
public IDictionary<Occurance, ISearchSubQuery> PostFilterQuery { get; set; }
public string Index { get; set; }
public DateTime? PreviewAt { get; set; }
void Add(Occurance queryOccurance, ISearchSubQuery booleanQueryQuery);
}

public interface ISearchQuery
{

public int Page { get; set; }
public int PageSize { get; set; }
public string Index { get; set; }

}
}
11 changes: 11 additions & 0 deletions src/SImpl.SearchModule.Abstraction/Queries/MultiSearchQuery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Collections.Generic;
using SImpl.CQRS.Queries;
using SImpl.SearchModule.Abstraction.Models;

namespace SImpl.SearchModule.Abstraction.Queries
{
public class MultiSearchQuery : IMultiSearchQuery, IQuery<IMultiSearchQueryResult>
{
public IDictionary<string, ISearchQuery<ISearchModel>> Queries { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Nest;
using SImpl.CQRS.Queries;
using SImpl.SearchModule.Abstraction.Handlers;
using SImpl.SearchModule.Abstraction.Models;
using SImpl.SearchModule.Abstraction.Queries;
using SImpl.SearchModule.Abstraction.Results;
using SImpl.SearchModule.ElasticSearch.Application.Services;
using SImpl.SearchModule.ElasticSearch.Application.Services.MultiSearch;
using SImpl.SearchModule.ElasticSearch.Application.Services.Result;
using SImpl.SearchModule.ElasticSearch.Configuration;
using SImpl.SearchModule.ElasticSearch.Models;
using IAggregation = SImpl.SearchModule.Abstraction.Models.IAggregation;
using IBucket = Nest.IBucket;

namespace SImpl.SearchModule.ElasticSearch.Application.QueryHandlers
{
public class ElasticSearchMultiSearchQueryHandler : IQueryHandler<MultiSearchQuery, IMultiSearchQueryResult>
{
private IElasticSearchMultiQueryTranslatorService _translatorService;
private readonly IElasticClient _client;
private readonly ILogger<ElasticSearchMultiSearchQueryHandler> _logger;
private readonly ElasticSearchConfiguration _configuration;
private readonly IEnumerable<IAggregationTranslationService> _collection;

public ElasticSearchMultiSearchQueryHandler(IElasticSearchMultiQueryTranslatorService translatorService,
IElasticClient client,
ILogger<ElasticSearchMultiSearchQueryHandler> logger, ElasticSearchConfiguration configuration,
IEnumerable<IAggregationTranslationService> collection)
{
_translatorService = translatorService;
_client = client;
_logger = logger;
_configuration = configuration;
_collection = collection;
}

public async Task<IMultiSearchQueryResult> HandleAsync(MultiSearchQuery query)
{
MultiSearchDescriptor searchDescriptor = _translatorService.Translate(query);

MultiSearchResponse result =
await _client.MultiSearchAsync(searchDescriptor);
if (_configuration.UseDebugStream)
{
_logger.LogInformation(result.DebugInformation);
_logger.LogInformation(searchDescriptor.ToString());
}

var resultModel = new MultiSearchQueryResult()
{
Results = new Dictionary<string, IQueryResult>()
};
foreach (var singularQuery in query.Queries)
{
var searchResponse = result.GetResponse<ElasticSearchModel>(singularQuery.Key);
if (searchResponse.IsValid)
{
resultModel.Results.Add(singularQuery.Key, new SimplQueryResult()
{
SearchModels = searchResponse.Documents.Select(ElasticSearchModelMapper.Map).ToList(),
Aggregations = TranslateAggregations(searchResponse.Aggregations),
Pagination = new Pagination()
{
CurrentPage = singularQuery.Value.Page,
PageSize = singularQuery.Value.PageSize,
Total = searchResponse.Total,
TotalNumberOfPages =
(int)Math.Ceiling((searchResponse.Total / (double)singularQuery.Value.PageSize))
},
HighLighter = TranslateHighLighter(searchResponse.Hits)
});
}
}

return resultModel;
}


private HighLighter TranslateHighLighter(IReadOnlyCollection<IHit<ElasticSearchModel>> resultHits)
{
var highLghter = new HighLighter();
foreach (var hit in resultHits)
{
foreach (var highlightHit in hit.Highlight)
{
highLghter.Add(highlightHit.Key, highlightHit.Value.Select(x => x as object).ToList());
}
}

return highLghter;
}

private List<IAggregation> TranslateAggregations(AggregateDictionary resultAggregations)
{
var list = new List<IAggregation>();

foreach (var aggregation in resultAggregations)
{
var aggregationModel = TranslateAggregate(aggregation);
list.Add(aggregationModel);
}

return list;
}

//todo: figure out if we can simplify stuff there
private IAggregation TranslateAggregate(KeyValuePair<string, IAggregate> aggregation)
{
var type = aggregation.Value.GetType();
var handlerType =
typeof(IAggregationTranslationService<>).MakeGenericType(type);
var translator =
_collection.FirstOrDefault(x => x.GetType().GetInterfaces().Any(x => x == handlerType));
var aggregationModel = translator.Translate(aggregation);
aggregationModel.NestedAggregation = TranslateSubAggregate(aggregation.Value);
return aggregationModel;
}

private List<IAggregation> TranslateSubAggregate(IAggregate aggregationValue)
{
var list = new List<IAggregation>();
//todo: add other options of buckets in future
switch (aggregationValue)
{
case BucketAggregate keyedBucket:
list.AddRange(keyedBucket.Items.Select(x => x as KeyedBucket<object>)
.SelectMany(x => x.Select(y => TranslateAggregate(y))));
break;
case SingleBucketAggregate singleBucketAggregate:
list.AddRange(singleBucketAggregate.Select(y => TranslateAggregate(y)));
break;
}

return list;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Nest;
using SImpl.SearchModule.Abstraction.Models;
using SImpl.SearchModule.Abstraction.Queries;
using SImpl.SearchModule.ElasticSearch.Models;

namespace SImpl.SearchModule.ElasticSearch.Application.Services.MultiSearch
{
public class ElasticSearchMultiQueryTranslatorService : IElasticSearchMultiQueryTranslatorService
{
private readonly IElasticSearchQueryTranslatorService _elasticSearchQueryTranslatorService;

public ElasticSearchMultiQueryTranslatorService(IElasticSearchQueryTranslatorService elasticSearchQueryTranslatorService)
{
_elasticSearchQueryTranslatorService = elasticSearchQueryTranslatorService;
}

public MultiSearchDescriptor Translate(MultiSearchQuery query)
{
var descriptor = new MultiSearchDescriptor();
foreach (var keyedQuery in query.Queries)
{
descriptor.Search<ISearchModel>(keyedQuery.Key,
n => _elasticSearchQueryTranslatorService.Translate<ISearchModel>(keyedQuery.Value));

}

return descriptor;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Nest;
using SImpl.SearchModule.Abstraction.Queries;

namespace SImpl.SearchModule.ElasticSearch.Application.Services.MultiSearch
{
public interface IElasticSearchMultiQueryTranslatorService
{
MultiSearchDescriptor Translate(MultiSearchQuery query);
}
}
2 changes: 2 additions & 0 deletions src/SImpl.SearchModule.ElasticSearch/ElasticSearchModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using SImpl.SearchModule.Abstraction.Queries;
using SImpl.SearchModule.Core.Application.Services;
using SImpl.SearchModule.ElasticSearch.Application.Services;
using SImpl.SearchModule.ElasticSearch.Application.Services.MultiSearch;
using SImpl.SearchModule.ElasticSearch.Application.Services.Result;
using SImpl.SearchModule.ElasticSearch.Application.Services.SubQueries;
using SImpl.SearchModule.ElasticSearch.Configuration;
Expand Down Expand Up @@ -45,6 +46,7 @@ public void ConfigureServices(IServiceCollection services)
services.AddTransient(typeof(IElasticSearchClientFactory), typeof(ElasticSearchClientFactory));
services.AddTransient(typeof(IElasticClient), provider => provider.GetService<IElasticSearchClientFactory>().CreateClient());
services.AddTransient<IElasticSearchQueryTranslatorService, BaseElasticSearchQueryTranslatorService>();
services.AddTransient<IElasticSearchMultiQueryTranslatorService, ElasticSearchMultiQueryTranslatorService>();
services.AddTransient(typeof(IIndexingService),
Config.SearchService);
services.Scan(s =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,45 @@

namespace SImpl.SearchModule.FluentApi.Configuration
{
public class FluentApiMultiSearchQueryCreator : IFluentApiMultiSearchQueryCreator
{
private IMultiSearchQuery _baseQuery { get; set; }

public FluentApiMultiSearchQueryCreator()
{
_baseQuery = new MultiSearchQuery();
}
public IMultiSearchQuery Compile()
{
return _baseQuery;
}
public FluentApiMultiSearchQueryCreator CreateSearchQuery(string key, SearchQuery searchQuery,Action<IBaseQueryConfigurator> configurator )
{
var baseQuery = new QueryCreatorConfigurator(searchQuery);
var query = new FluentApiSearchQueryCreator(baseQuery.Query)
.CreateSearchQuery(queryConfigurator => configurator.Invoke(new FluentQueryConfigurator(baseQuery.Query)));
_baseQuery.Queries.Add(key,query );
return this;
}
public FluentApiMultiSearchQueryCreator CreateSearchQuery(string key,Action<QueryCreatorConfigurator> searchQuery,Action<IBaseQueryConfigurator> configurator )
{
var baseQuery = new QueryCreatorConfigurator(new SearchQuery());
searchQuery.Invoke(baseQuery);
var query = new FluentApiSearchQueryCreator(baseQuery.Query)
.CreateSearchQuery(queryConfigurator => configurator.Invoke(new FluentQueryConfigurator(baseQuery.Query)));
_baseQuery.Queries.Add(key,query );
return this;
}
}

public interface IFluentApiMultiSearchQueryCreator
{
FluentApiMultiSearchQueryCreator CreateSearchQuery(string key, Action<QueryCreatorConfigurator> searchQuery,
Action<IBaseQueryConfigurator> configurator);

IMultiSearchQuery Compile();
}

public class FluentApiSearchQueryCreator : IFluentApiSearchQueryCreator
{
private ISearchQuery<IQueryResult> _baseQuery { get; set; }
Expand Down
13 changes: 13 additions & 0 deletions src/Simpl.SearchModule.TestApi/Controllers/SearchApiTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@ public async Task<SimplQueryResult> Get(SearchRequest request)
{
try
{
var multiSearchQuery = new FluentApiMultiSearchQueryCreator().CreateSearchQuery("test", f =>
{
f.WithIndex("test")
}, query =>
{
query.CreateAggregationQuery(f =>
{

f.CreateFilterQuery();
f.CreateTermQuery(x=>x.WithName().WithField())
})
query.CreateBoolQuery()
});
var query = new FluentApiSearchQueryCreator(new SearchQuery()
{
Index = "headlesssearchindex",
Expand Down