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 { /// /// implementation based on Lucene.NET /// public class LuceneQuoteSearcher : IQuoteSearcher { private readonly ISearchIndexLocator indexLocator; private readonly IRepository quoteRepository; private readonly Analyzer analyzer = new StandardAnalyzer(); private readonly QueryParser queryParser; public LuceneQuoteSearcher(ISearchIndexLocator indexLocator, IRepository quoteRepository) { this.indexLocator = indexLocator; this.quoteRepository = quoteRepository; queryParser = new QueryParser("text", analyzer); } [UnitOfWork] public IEnumerable Search(string searchString) { if (string.IsNullOrWhiteSpace(searchString)) { return Enumerable.Empty(); } 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; } } }