vgquotes/Src/VideoGameQuotes.Api/Search/Lucene/LuceneQuoteSearcher.cs

58 lines
2.0 KiB
C#

using System.Collections.Generic;
using System.Linq;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.QueryParsers;
using Lucene.Net.Search;
using Portoa.Persistence;
namespace VideoGameQuotes.Api.Search.Lucene {
/// <summary>
/// <see cref="IQuoteSearcher"/> implementation based on <c>Lucene.NET</c>
/// </summary>
public class LuceneQuoteSearcher : IQuoteSearcher {
private readonly ISearchIndexLocator indexLocator;
private readonly IRepository<Quote> quoteRepository;
private readonly Analyzer analyzer = new StandardAnalyzer();
private readonly QueryParser queryParser;
public LuceneQuoteSearcher(ISearchIndexLocator indexLocator, IRepository<Quote> quoteRepository) {
this.indexLocator = indexLocator;
this.quoteRepository = quoteRepository;
queryParser = new QueryParser("text", analyzer);
}
[UnitOfWork]
public IEnumerable<SearchResult> Search(string searchString) {
var query = queryParser.Parse(QueryParser.Escape(searchString));
var searcher = new IndexSearcher(indexLocator.IndexDirectory);
return searcher
.Search(query)
.ToEnumerable()
.Select(hit => new SearchResult {
Score = hit.GetScore(),
Quote = quoteRepository.FindById(int.Parse(hit.GetDocument().GetField("id").StringValue()))
});
}
[UnitOfWork]
public void BuildIndex(bool replaceOldIndex = true) {
var indexWriter = new IndexWriter(indexLocator.IndexDirectory, analyzer, replaceOldIndex);
foreach (var quote in quoteRepository.Records) {
indexWriter.AddDocument(CreateDocument(quote));
}
indexWriter.Optimize();
indexWriter.Close();
}
private static Document CreateDocument(Quote quote) {
var document = new Document();
document.Add(new Field("id", quote.Id.ToString(), Field.Store.YES, Field.Index.NO));
document.Add(new Field("text", quote.Text, Field.Store.YES, Field.Index.TOKENIZED));
return document;
}
}
}