using System;
using System.Collections.Generic;
using System.Linq;
using Lucene.Net.QueryParsers;
using Lucene.Net.Search;
using Portoa.Persistence;
using VideoGameQuotes.Api.Persistence;
using Directory = Lucene.Net.Store.Directory;
namespace VideoGameQuotes.Api.Search.Lucene {
///
/// implementation for entities based on Lucene.NET
///
public class LuceneEntitySearcher : ISearcher where T : Entity {
private readonly QueryParser queryParser;
private readonly Directory indexDirectory;
private readonly ISearchService searchService;
public LuceneEntitySearcher(QueryParser queryParser, Directory indexDirectory, ISearchService searchService) {
this.queryParser = queryParser;
this.indexDirectory = indexDirectory;
this.searchService = searchService;
}
public IEnumerable> Search(string searchString, int maxResults = 10) {
if (string.IsNullOrWhiteSpace(searchString)) {
return Enumerable.Empty>();
}
if (maxResults < 0) {
throw new ArgumentOutOfRangeException("maxResults", maxResults, "Maximum number of results must be greater than or equal to zero");
}
if (maxResults == 0) {
maxResults = int.MaxValue;
}
var query = queryParser.Parse(QueryParser.Escape(searchString));
var searcher = new IndexSearcher(indexDirectory, true);
try {
var docs = searcher
.Search(query, maxResults)
.scoreDocs;
var quotes = searchService.FindByIds(docs.Select(doc => int.Parse(searcher.Doc(doc.doc).GetField("id").StringValue())));
return quotes.Zip(docs, (entity, doc) => new SearchResult { Entity = entity, Score = doc.score }).ToArray();
} finally {
searcher.Close();
}
}
}
}