Exemple #1
0
        public TraineeshipSearchResponse Search(TraineeshipSearchRequestParameters searchParameters)
        {
            var results = PerformSearch(searchParameters);

            var response = new TraineeshipSearchResponse(results.Total, results.Documents, searchParameters);

            return(response);
        }
 public TraineeshipSearchResponse(
     long total,
     IEnumerable <TraineeshipSearchResult> results,
     TraineeshipSearchRequestParameters searchParameters)
 {
     Total            = total;
     Results          = results;
     SearchParameters = searchParameters;
 }
Exemple #3
0
        private static int GetGeoDistanceSortHitPosition(TraineeshipSearchRequestParameters parameters)
        {
            switch (parameters.SortType)
            {
            case VacancySearchSortType.Distance:
                return(0);

            default:
                return(1);
            }
        }
        public void Search_ShouldSearchByVacancyReference()
        {
            var parameters = new TraineeshipSearchRequestParameters
            {
                Latitude         = 52.4173666904458,
                Longitude        = -1.88983017452229,
                PageNumber       = 1,
                PageSize         = 5,
                SearchRadius     = 40,
                VacancyReference = "1104004"
            };

            const string expectedJsonQuery = "{\"from\":0,\"query\":{\"bool\":{\"filter\":[{\"term\":{\"vacancyReference\":{\"value\":\"1104004\"}}}]}},\"size\":5,\"sort\":[{\"_score\":{\"order\":\"desc\"}},{\"_geo_distance\":{\"distance_type\":\"arc\",\"unit\":\"mi\",\"location\":[{\"lat\":52.4173666904458,\"lon\":-1.88983017452229}]}}],\"track_scores\":true}";

            AssertSearch(parameters, expectedJsonQuery);
        }
        public void Search_ShouldSearchByLatAndLong()
        {
            var parameters = new TraineeshipSearchRequestParameters
            {
                Latitude     = 52.4173666904458,
                Longitude    = -1.88983017452229,
                PageNumber   = 1,
                PageSize     = 5,
                SearchRadius = 40.5d,
                SortType     = VacancySearchSortType.Distance,
            };

            const string expectedJsonQuery = "{\"from\":0,\"query\":{\"bool\":{\"filter\":[{\"geo_distance\":{\"distance\":\"40.5mi\",\"location\":{\"lat\":52.4173666904458,\"lon\":-1.88983017452229}}}]}},\"size\":5,\"sort\":[{\"_geo_distance\":{\"distance_type\":\"arc\",\"unit\":\"mi\",\"location\":[{\"lat\":52.4173666904458,\"lon\":-1.88983017452229}]}}],\"track_scores\":true}";

            AssertSearch(parameters, expectedJsonQuery);
        }
        public void Search_ShouldIncludeGeoDistanceInSort()
        {
            var parameters = new TraineeshipSearchRequestParameters
            {
                DisabilityConfidentOnly = true,
                Latitude     = 52.4173666904458,
                Longitude    = -1.88983017452229,
                PageNumber   = 1,
                PageSize     = 5,
                SearchRadius = null,
                SortType     = VacancySearchSortType.RecentlyAdded,
            };

            const string expectedJsonQuery = "{\"from\":0,\"query\":{\"match\":{\"isDisabilityConfident\":{\"query\":\"true\"}}},\"size\":5,\"sort\":[{\"postedDate\":{\"order\":\"desc\"}},{\"_geo_distance\":{\"distance_type\":\"arc\",\"unit\":\"mi\",\"location\":[{\"lat\":52.4173666904458,\"lon\":-1.88983017452229}]}}],\"track_scores\":true}";

            AssertSearch(parameters, expectedJsonQuery);
        }
Exemple #7
0
        private QueryContainer GetQuery(TraineeshipSearchRequestParameters parameters, QueryContainerDescriptor <TraineeshipSearchResult> q)
        {
            if (!string.IsNullOrEmpty(parameters.VacancyReference))
            {
                return(q.Bool(fq =>
                              fq.Filter(f =>
                                        f.Term(t =>
                                               t.VacancyReference, parameters.VacancyReference))));
            }

            QueryContainer query = null;

            if (parameters.DisabilityConfidentOnly)
            {
                // Nest package won't allow a boolean directly and has to be a string
                // Elastic will throw if its not lower case
                // As we specifically only add this when this statement is true, explicit value is passed.
                var queryDisabilityConfidentOnly = q
                                                   .Match(m => m.Field(f => f.IsDisabilityConfident)
                                                          .Query("true"));

                query &= queryDisabilityConfidentOnly;
            }

            if (parameters.Ukprn.HasValue)
            {
                var queryClause = q
                                  .Match(m => m.Field(f => f.Ukprn)
                                         .Query(parameters.Ukprn.ToString()));
                query &= queryClause;
            }

            if (parameters.CanFilterByGeoDistance)
            {
                var geoQueryClause = q.Bool(qf => qf.Filter(f => f
                                                            .GeoDistance(vs => vs
                                                                         .Field(field => field.Location)
                                                                         .Location(parameters.Latitude.Value, parameters.Longitude.Value)
                                                                         .Distance(parameters.SearchRadius.Value, DistanceUnit.Miles))));

                query &= geoQueryClause;
            }

            return(query);
        }
        public void Search_ShouldSearchByCombination()
        {
            var parameters = new TraineeshipSearchRequestParameters
            {
                DisabilityConfidentOnly = true,
                Latitude     = 52.4173666904458,
                Longitude    = -1.88983017452229,
                Ukprn        = 12345678,
                PageNumber   = 1,
                PageSize     = 5,
                SearchRadius = 40.5d,
                SortType     = VacancySearchSortType.Distance,
            };

            const string expectedJsonQuery = "{\"from\":0,\"query\":{\"bool\":{\"filter\":[{\"geo_distance\":{\"distance\":\"40.5mi\",\"location\":{\"lat\":52.4173666904458,\"lon\":-1.88983017452229}}}],\"must\":[{\"match\":{\"isDisabilityConfident\":{\"query\":\"true\"}}},{\"match\":{\"ukprn\":{\"query\":\"12345678\"}}}]}},\"size\":5,\"sort\":[{\"_geo_distance\":{\"distance_type\":\"arc\",\"location\":[{\"lat\":52.4173666904458,\"lon\":-1.88983017452229}],\"unit\":\"mi\"}}],\"track_scores\":true}";

            AssertSearch(parameters, expectedJsonQuery);
        }
Exemple #9
0
        private ISearchResponse <TraineeshipSearchResult> PerformSearch(TraineeshipSearchRequestParameters parameters)
        {
            var results = _elasticClient.Search <TraineeshipSearchResult>(s =>
            {
                s.Index(_indexName);
                s.Skip((parameters.PageNumber - 1) * parameters.PageSize);
                s.Take(parameters.PageSize);

                s.TrackScores();

                s.Query(q => GetQuery(parameters, q));

                SetSort(s, parameters);

                return(s);
            });

            SetHitValuesOnSearchResults(parameters, results);

            return(results);
        }
        private void AssertSearch(TraineeshipSearchRequestParameters parameters, string expectedJsonQuery)
        {
            var searchResponse = new Mock <ISearchResponse <TraineeshipSearchResult> >();

            searchResponse.Setup(s => s.Total).Returns(0);
            searchResponse.Setup(s => s.Documents).Returns(Enumerable.Empty <TraineeshipSearchResult>().ToList());

            Func <SearchDescriptor <TraineeshipSearchResult>, ISearchRequest> actualSearchDescriptorFunc = null;

            var mockClient = new Mock <IElasticClient>();

            mockClient.Setup(c => c.Search <TraineeshipSearchResult>(It.IsAny <Func <SearchDescriptor <TraineeshipSearchResult>, ISearchRequest> >()))
            .Callback <Func <SearchDescriptor <TraineeshipSearchResult>, ISearchRequest> >(d => actualSearchDescriptorFunc = d)
            .Returns(searchResponse.Object);

            var mockFactory = new Mock <IElasticClientFactory>();

            mockFactory.Setup(f => f.CreateClient(It.IsAny <Action <IApiCallDetails> >())).Returns(mockClient.Object);

            var mockLogger = new Mock <ILog>();

            var sut = new TraineeshipSearchClient(mockFactory.Object, "traineeships", mockLogger.Object);

            var response = sut.Search(parameters);

            var baseSearchDescriptor = new SearchDescriptor <TraineeshipSearchResult>();
            var query = actualSearchDescriptorFunc(baseSearchDescriptor);

            var elasticClient = new ElasticClient();
            var stream        = new MemoryStream();

            elasticClient.RequestResponseSerializer.Serialize(query, stream);
            var actualJsonQuery = System.Text.Encoding.UTF8.GetString(stream.ToArray());

            var actualJsonQueryJToken = JToken.Parse(actualJsonQuery);

            var expectedJsonQueryJToken = JToken.Parse(expectedJsonQuery);

            actualJsonQueryJToken.Should().BeEquivalentTo(expectedJsonQueryJToken);
        }
Exemple #11
0
        private void SetHitValuesOnSearchResults(TraineeshipSearchRequestParameters searchParameters, ISearchResponse <TraineeshipSearchResult> results)
        {
            foreach (var result in results.Documents)
            {
                var hitMd = results.Hits.First(h => h.Id == result.Id.ToString(CultureInfo.InvariantCulture));

                if (searchParameters.CanSortByGeoDistance)
                {
                    try
                    {
                        var distance = hitMd.Sorts.ElementAt(GetGeoDistanceSortHitPosition(searchParameters));
                        result.Distance = Convert.ToDouble(distance);
                    }
                    catch (Exception e)
                    {
                        _logger?.Error(e, "Error converting distance sort value from Elastic Result Set");
                        result.Distance = 0;
                    }
                }

                result.Score = hitMd.Score.GetValueOrDefault(0);
            }
        }
Exemple #12
0
        internal static SortDescriptor <TraineeshipSearchResult> TrySortByGeoDistance(this SortDescriptor <TraineeshipSearchResult> sortDescriptor, TraineeshipSearchRequestParameters searchParameters)
        {
            if (searchParameters.CanSortByGeoDistance)
            {
                sortDescriptor.GeoDistance(g => g
                                           .Field(f => f.Location)
                                           .DistanceType(GeoDistanceType.Arc)
                                           .Unit(DistanceUnit.Miles)
                                           .Points(new GeoLocation(searchParameters.Latitude.Value, searchParameters.Longitude.Value)));
            }

            return(sortDescriptor);
        }
Exemple #13
0
        private static void SetSort(SearchDescriptor <TraineeshipSearchResult> search, TraineeshipSearchRequestParameters parameters)
        {
            switch (parameters.SortType)
            {
            case VacancySearchSortType.RecentlyAdded:
                search.Sort(s => s
                            .Descending(r => r.PostedDate)
                            .TrySortByGeoDistance(parameters));
                break;

            case VacancySearchSortType.Distance:
                search.Sort(s => s
                            .TrySortByGeoDistance(parameters));
                break;

            case VacancySearchSortType.ClosingDate:
                search.Sort(s => s
                            .Ascending(r => r.ClosingDate)
                            .TrySortByGeoDistance(parameters));
                break;

            default:
                search.Sort(s => s
                            .Descending(SortSpecialField.Score)
                            .TrySortByGeoDistance(parameters));
                break;
            }
        }