public async Task <RelevancyScoreResult <T> > ScoreAsync <T>( SearchQueryRelevancyScores <T> query, string baseUrl, int resultsToEvaluate) { var response = await _searchClient.SearchAsync( baseUrl, query.SearchQuery, resultsToEvaluate); if (!query.PackageIdToScore.Any() || query.PackageIdToScore.Max(x => x.Value) == 0) { return(new RelevancyScoreResult <T>( 0, query, response)); } var patternToScorePairs = new List <KeyValuePair <Regex, int> >(); foreach (var pair in query.PackageIdToScore.Where(x => x.Value > 0)) { if (WildcardUtility.IsWildcard(pair.Key)) { patternToScorePairs.Add(new KeyValuePair <Regex, int>( WildcardUtility.GetPackageIdWildcareRegex(pair.Key), pair.Value)); } } // Determine the score for each of the returns package IDs. var scores = new List <int>(); for (var i = 0; i < response.Data.Count; i++) { var packageId = response.Data[i].Id; if (query.PackageIdToScore.TryGetValue(packageId, out var score)) { scores.Add(score); } else { // It might be that the score map contains wildcards. Let's try those. Execute them from longest to // shortest. This is a hueristic to perform the most specific ones first. var match = false; foreach (var pair in patternToScorePairs.OrderByDescending(x => x.Key.ToString().Length)) { if (pair.Key.IsMatch(packageId)) { scores.Add(pair.Value); patternToScorePairs.Remove(pair); match = true; break; } } if (match) { continue; } scores.Add(0); } } // Determine the ideal scores by taking the top N scores. var idealScores = query .PackageIdToScore .Select(x => x.Value) .OrderByDescending(x => x) .Take(resultsToEvaluate); // Calculate the NDCG. var resultScore = NDCG(scores, idealScores); if (resultScore > 1.0) { throw new InvalidOperationException("An NDCG score cannot be greater than 1.0. There's a bug!"); } return(new RelevancyScoreResult <T>( resultScore, query, response)); }
public RelevancyScoreResult(double resultScore, SearchQueryRelevancyScores input, SearchResponse response) { ResultScore = resultScore; Input = input; Response = response; }