Skip to content

Instantly share code, notes, and snippets.

@mattbrailsford
Last active December 10, 2017 11:42
Show Gist options
  • Save mattbrailsford/76dd71466098f184c342ab485fac2f3b to your computer and use it in GitHub Desktop.
Save mattbrailsford/76dd71466098f184c342ab485fac2f3b to your computer and use it in GitHub Desktop.
Random results with Examine
using System.Collections.Generic;
using System.Linq;
using Examine;
using Examine.LuceneEngine;
using Helpers;
namespace Extensions
{
public static class ExamineExtensions
{
public static IEnumerable<SearchResult> RandomResults(this ISearchResults results, int count)
{
var searchResults = results as SearchResults;
if (searchResults == null) return Enumerable.Empty<SearchResult>();
var totalResults = searchResults.TopDocs?.ScoreDocs.Length ?? 0;
if (totalResults == 0) return Enumerable.Empty<SearchResult>();
var randomIndexes = MathHelper.GenerateUniqueRandomSequence(count, 0, totalResults - 1);
var docs = randomIndexes.Select(idx => results.Skip(idx).First()).ToList();
return docs;
}
public static SearchResult RandomResult(this ISearchResults results)
{
return results.RandomResults(1).FirstOrDefault();
}
}
}
public class Example
{
public void DoSearch()
{
var searcher = ExamineManager.Instance.SearchProviderCollection["ExternalSearcher"];
var criteria = searcher.CreateSearchCriteria()
.Field("myField", "myValue") // Expand on this for you query
.Compile();
var results = searcher.Search(criteria).RandomResults(3);
// TODO: Convert results to typed content etc
}
}
using System;
using System.Collections.Generic;
using System.Linq;
namespace Helpers
{
public static class MathHelper
{
public static IReadOnlyList<int> GenerateUniqueRandomSequence(int count, int min, int max)
{
var sample = Enumerable.Range(min, (max - min) + 1).ToList();
var results = new List<int>();
var rand = new Random(Guid.NewGuid().GetHashCode());
for (var i = 0; i < count; i++)
{
if (sample.Count > 0)
{
var sampleIdx = rand.Next(1, sample.Count) - 1;
results.Add(sample[sampleIdx]);
sample.RemoveAt(sampleIdx);
}
}
return results;
}
}
}
@mattbrailsford
Copy link
Author

Using ISearchResults.Skip should be pretty efficient in this context. Internally, the SearchResults implementation does a yield return, so only the results we access get evaluated and fetched from the lucene docs collection so we should only be populating the docs we need.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment