Created
September 13, 2011 16:53
-
-
Save mattwarren/1214297 to your computer and use it in GitHub Desktop.
Faceted search SO example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Linq; | |
using System.Linq.Expressions; | |
using Raven.Abstractions.Data; | |
using Raven.Abstractions.Indexing; | |
using Raven.Client; | |
using Raven.Client.Linq; | |
namespace Raven.Tests.Faceted | |
{ | |
public class StackoverflowFacetedIndex : RavenTest | |
{ | |
private readonly List<Facet> _facets; | |
public StackoverflowFacetedIndex() | |
{ | |
_facets = new List<Facet> { new Facet {Name = "Tag"} }; | |
} | |
public void StackoverflowTest() | |
{ | |
using (var store = NewDocumentStore()) | |
{ | |
ExecuteTest(store); | |
} | |
} | |
private void ExecuteTest(IDocumentStore store) | |
{ | |
using (var s = store.OpenSession()) | |
{ | |
s.Store(new FacetSetup { Id = "facets/TagFacets", Facets = _facets }); | |
s.SaveChanges(); | |
store.DatabaseCommands.PutIndex("QuestionTags", | |
new IndexDefinition | |
{ | |
Map = | |
@"from question in docs | |
from tag in question.Tags | |
select new | |
{ | |
question.CreatedOn, | |
Tag = tag | |
}" | |
}); | |
var counter = 0; | |
var sampleData = GetSampleData(); | |
foreach (var qu in sampleData) | |
{ | |
s.Store(qu); | |
counter++; | |
if (counter % 1024 == 0) | |
s.SaveChanges(); | |
} | |
s.SaveChanges(); | |
// Issue a query to make sure the index isn't stale | |
var result = s.Query<Question>("QuestionTags") | |
.Customize(x => x.WaitForNonStaleResults()) | |
.ToList(); | |
//WaitForUserToContinueTheTest(store as EmbeddableDocumentStore); | |
var expressions = new Expression<Func<Question, bool>>[] | |
{ | |
//Matches all docs | |
x => x.CreatedOn >= new DateTime(1900, 1, 1), | |
//Only matches 2 questions (hence tag count should be different) | |
x => x.CreatedOn >= new DateTime(2008, 5, 7), | |
//Only matches 1 question | |
x => x.CreatedOn >= new DateTime(2008, 5, 20), | |
}; | |
foreach (var exp in expressions) | |
{ | |
Console.WriteLine("Query: " + exp); | |
var facetQueryTimer = Stopwatch.StartNew(); | |
var facetResults = s.Query<Question>("QuestionTags") | |
.Where(exp) | |
.ToFacets("facets/TagFacets"); | |
facetQueryTimer.Stop(); | |
//Console.WriteLine("Took {0:0.00} msecs", facetQueryTimer.ElapsedMilliseconds); | |
var filteredData = sampleData | |
.Where(exp.Compile()) | |
.SelectMany(x => x.Tags) | |
.GroupBy(tag => tag) | |
.Select(grp => new { Tag = grp.Key, Count = grp.Count()}) | |
.ToList(); | |
foreach (var tagCount in filteredData) | |
{ | |
var matchingTag = tagCount.Tag.ToLowerInvariant(); | |
var match = facetResults["Tag"].FirstOrDefault(x => x.Range == matchingTag); | |
if (match == null || match.Count != tagCount.Count) | |
{ | |
Console.WriteLine("Tag {0}, expected {1}, got {2}", | |
tagCount.Tag, tagCount.Count, match == null ? "<null>" : match.Count.ToString()); | |
} | |
} | |
var facetList = facetResults["Tag"].Select(x => String.Format("{0} - {1}", x.Range, x.Count)); | |
Console.WriteLine("Results: {0}\n", String.Join(", ", facetList)); | |
} | |
} | |
} | |
private static IEnumerable<Question> GetSampleData() | |
{ | |
yield return new Question | |
{ | |
Subject = "Pew Pew", | |
CreatedOn = new DateTime(2008, 5, 12), | |
UserId = "Users/Justin", | |
Tags = new[] {"C#", ".NET", "Regex"} | |
}; | |
yield return new Question | |
{ | |
Subject = " RuRoh :( ", | |
CreatedOn = new DateTime(2008, 5, 3), | |
UserId = "Users/Ayende", | |
Tags = new[] {"C#", ".NET"} | |
}; | |
yield return new Question | |
{ | |
Subject = "How do I get the codeZ??", | |
CreatedOn = new DateTime(2008, 5, 20), | |
UserId = "Users/Matt", | |
Tags = new[] {"Ruby"} | |
}; | |
} | |
} | |
public class User | |
{ | |
public string Id { get; set; } | |
public string DisplayName { get; set; } | |
} | |
public class Question | |
{ | |
public string Id { get; set; } | |
public string UserId { get; set; } // Reference to User.Id | |
public string Subject { get; set; } | |
public DateTime CreatedOn { get; set; } // Utc of course :) | |
public IList<string> Tags { get; set; } // Tag Id's. (eg. tags/1 tags/2 ...) | |
} | |
public class Tag | |
{ | |
public string Id { get; set; } | |
public string Name { get; set; } | |
public IList<string> Aliases { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment