ayende/ravendb — pull request #178 by SHSE (2012-11-26 13:53:07+00:00)
Title: Full text search result highlighting

# Summary
I have implemented result highlighting for RavenDB full text search.
It uses Lucene FastVectorHighlighter to extract highlighting fragments from Lucene document.
In order to work, Lucene field needs to be `ANALYSED` or `ANALYZED_NO_NORMS`, stored and term vector needs to be `WITH_POSITIONS_OFFSETS`.

# Features
* Simple query over static index
* Map only index
* MapReduce index
* Dynamic query
* Query with projection

## Static index

```C#
store.DatabaseCommands.PutIndex("MyStaticIndex",
new IndexDefinition
{
Map = @"from blog in docs.Blogs
select new { blog.Title, blog.Category }",
Stores =
{
{"Title", FieldStorage.Yes}, // Highlighted field must be stored
{"Category", FieldStorage.Yes} // Highlighted field must be stored
},
Indexes =
{
{"Title", FieldIndexing.Analyzed}, // Highlighted field must be analysed
{"Category", FieldIndexing.Analyzed} // Highlighted field must be analysed
}
});

FieldHighlightings titleHighlightings = null;
FieldHighlightings categoryHighlightings = null;

var results = session.Query(indexName)
.Customize(
c =>
// Put highlighting fragments for Title into titleHighlightings variable
c.Highlight("Title", 18, 2, out titleHighlightings)
// Put highlighting fragments for Category into categoryHighlightings variable
.Highlight("Category", 18, 2, out categoryHighlightings)
.SetHighlighterTags("*", "*") // Set tags to wrap each fragment with
.WaitForNonStaleResultsAsOfNow())
.Search(x => x.Category, "rhinos")
.Search(x => x.Title, "target word")
.ToArray();

foreach (var result in results)
{
Console.WriteLine(result.Title);
Console.WriteLine(string.Join("...", titleHighlightings.GetFragments(result.Id)));
}
```

## Projections

```C#
var results = session.Query(indexName)
.Customize(
c => c.WaitForNonStaleResults()
// Map highlighting fragments to TitleFragments property
.Highlight("Title", 18, 2, "TitleFragments"))
.Where(x => x.Title == "lorem" && x.Category == "ravens")
.Select(x => new
{
x.Title,
x.Category,
TitleFragments = default(string[])
})
.ToArray();

foreach (var result in results)
{
Console.WriteLine(result.Title);
Console.WriteLine(result.TitleFragments.First());
}
```