Thursday, September 6, 2012

NuGet Perf, Part VI AKA how to be the most popular dev around

NuGet Perf, Part VI AKA how to be the most popular dev around:
So far, we imported the NuGet data to RavenDB and seen how we can get it out for the packages page and then looked into how we can utilize RavenDB features to help us in package search. I think we did a good job there, but we can probably do better still. In this post, I am going to stop showing off things in the Studio and focus on code. In particular, advanced searching options.
We will start from the simplest search possible. Or not, because we are doing full text search and quite a few other things aside even in the base line search. Anyway, here is the skeleton program:

while (true)
{
Console.Write("Search: ");
var search = Console.ReadLine();
if(string.IsNullOrEmpty(search))
{
Console.Clear();
continue;
}
using (var session = store.OpenSession())
{
var q = session.Query<PackageSearch>("Packages/Search")
.Search(x => x.Query, search)
.Where(x => x.IsLatestVersion && x.IsAbsoluteLatestVersion && x.IsPrerelease == false)
.As<Package>()
.OrderByDescending(x => x.DownloadCount).ThenBy(x => x.Created)
.Take(3);
var packages = q.ToList();

foreach (var package in packages)
{
Console.WriteLine("\t{0}", package.Id);
}
}
}







Now, we are going to run this and see what we get.
image
So far, so good. Now let us try to improve things. What happens when we search for “jquryt”? Nothing is found, and that is actually pretty sad, because to a human, it is obvious what you are trying to search on.
If you have fat fingers and have a tendency to creatively spell words, I am sure you can emphasize with this feeling. Luckily for us, RavenDB is going to help, let us see how:
image
What?!
How did it do that? Well, let us look at the changes in the code, shall we?

private static void PeformQuery(IDocumentSession session, string search, bool guessIfNoResultsFound = true)
{
var packages = session.Query<PackageSearch>("Packages/Search")
.Search(x => x.Query, search)
.Where(x => x.IsLatestVersion && x.IsAbsoluteLatestVersion && x.IsPrerelease == false)
.As<Package>()
.OrderByDescending(x => x.DownloadCount).ThenBy(x => x.Created)
.Take(3).ToList();

if (packages.Count > 0)
{
foreach (var package in packages)
{
Console.WriteLine("\t{0}", package.Id);
}
}
else if(guessIfNoResultsFound)
{
DidYouMean(session, search);
}
else
{
Console.WriteLine("\tNo search results were found");
}
}


The only major change was the call to DidYouMean(), so let us see what is going on in there.

private static void DidYouMean(IDocumentSession session, string search)
{
var suggestionQueryResult = session.Query<PackageSearch>("Packages/Search")
.Search(x => x.Query, search)
.Suggest();
switch (suggestionQueryResult.Suggestions.Length)
{
case 0:
Console.WriteLine("\tNo search results were found");
break;
case 1:
// we may have it filtered because of the other conditions, don't recurse again
Console.WriteLine("\tSearch corrected to: {0}", suggestionQueryResult.Suggestions[0]);
Console.WriteLine();

PeformQuery(session, suggestionQueryResult.Suggestions[0], guessIfNoResultsFound: false);
break;
default:
Console.WriteLine("\tDid you mean?");
foreach (var suggestion in suggestionQueryResult.Suggestions)
{
Console.WriteLine("\t - {0} ?", suggestion);
}
break;
}
}




Here, we ask RavenDB, “we couldn’t find anything what we had, can you give me some other ideas?” RavenDB can check the actual data that we have on disk and suggest similar alternative.
In essence, we asked RavenDB for what is nearby, and it provided us with some useful suggestions. Because the suggestions are actually based on the data we have in the db, searches on that will produce correct results.
Note that we have three code paths here, if there is one suggestion, we are going to select that immediately. Let us see how this looks like in practice:
image
Users tend to fall in love with those sort of features, and with RavenDB you can provide them in just a few lines of code and absolutely no hassle.
In my next post (and probably the last in this series) we will discuss even more awesome search features Smile.


DIGITAL JUICE

No comments:

Post a Comment

Thank's!