diff --git a/Src/VideoGameQuotes.Api/Search/IQuoteSearcher.cs b/Src/VideoGameQuotes.Api/Search/IQuoteSearcher.cs deleted file mode 100644 index 32bb933..0000000 --- a/Src/VideoGameQuotes.Api/Search/IQuoteSearcher.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Collections.Generic; - -namespace VideoGameQuotes.Api.Search { - /// - /// Exposes an interface to search for quotes - /// - public interface IQuoteSearcher { - /// - /// Searches for quote based on the given search query - /// - IEnumerable Search(string query); - - /// - /// (Re)builds the search index - /// - /// Set to false to not overwrite the old index with a brand new one. - void BuildIndex(bool replaceOldIndex = true); - } -} \ No newline at end of file diff --git a/Src/VideoGameQuotes.Api/Search/ISearchIndexBuilder.cs b/Src/VideoGameQuotes.Api/Search/ISearchIndexBuilder.cs deleted file mode 100644 index e45b1a8..0000000 --- a/Src/VideoGameQuotes.Api/Search/ISearchIndexBuilder.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace VideoGameQuotes.Api.Search { - /// - /// Exposes an interface to build and update a search index - /// - public interface ISearchIndexBuilder { - /// - /// (Re)builds the search index - /// - void BuildIndex(); - - /// - /// Updates the index for the specified - /// - /// The object that needs its index updated - void UpdateIndex(T indexableObject); - } -} \ No newline at end of file diff --git a/Src/VideoGameQuotes.Api/Search/ISearchIndexLocator.cs b/Src/VideoGameQuotes.Api/Search/ISearchIndexLocator.cs deleted file mode 100644 index c12380c..0000000 --- a/Src/VideoGameQuotes.Api/Search/ISearchIndexLocator.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace VideoGameQuotes.Api.Search { - public interface ISearchIndexLocator { - string IndexDirectory { get; } - } - - public class SearchIndexLocator : ISearchIndexLocator { - private readonly string indexDirectory; - - public SearchIndexLocator(string indexDirectory) { - this.indexDirectory = indexDirectory; - } - - public string IndexDirectory { get { return indexDirectory; } } - } -} \ No newline at end of file diff --git a/Src/VideoGameQuotes.Api/Search/ISearcher.cs b/Src/VideoGameQuotes.Api/Search/ISearcher.cs deleted file mode 100644 index e75e8f8..0000000 --- a/Src/VideoGameQuotes.Api/Search/ISearcher.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; - -namespace VideoGameQuotes.Api.Search { - /// - /// Exposes an interface to perform a full-text search - /// - public interface ISearcher { - /// - /// Searches for records based on the given search query - /// - /// The search term(s) to search for - /// The maximum number of results to return (0 is unlimited); the default is 10 - IEnumerable> Search(string query, int maxResults = 10); - } -} \ No newline at end of file diff --git a/Src/VideoGameQuotes.Api/Search/Lucene/ILuceneDocumentHandler.cs b/Src/VideoGameQuotes.Api/Search/Lucene/ILuceneDocumentHandler.cs deleted file mode 100644 index bd1b778..0000000 --- a/Src/VideoGameQuotes.Api/Search/Lucene/ILuceneDocumentHandler.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Lucene.Net.Documents; -using Lucene.Net.Index; - -namespace VideoGameQuotes.Api.Search.Lucene { - public interface ILuceneDocumentHandler { - Document BuildDocument(T source); - Term GetIdTerm(T source); - } -} \ No newline at end of file diff --git a/Src/VideoGameQuotes.Api/Search/Lucene/LuceneEntityIndexBuilder.cs b/Src/VideoGameQuotes.Api/Search/Lucene/LuceneEntityIndexBuilder.cs deleted file mode 100644 index 382cea2..0000000 --- a/Src/VideoGameQuotes.Api/Search/Lucene/LuceneEntityIndexBuilder.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Lucene.Net.Index; -using Portoa.Logging; -using Portoa.Persistence; -using VideoGameQuotes.Api.Persistence; - -namespace VideoGameQuotes.Api.Search.Lucene { - public class LuceneEntityIndexBuilder : ISearchIndexBuilder where T : Entity { - private readonly ILogger logger; - private readonly IndexWriter indexWriter; - private readonly ISearchService searchService; - private readonly ILuceneDocumentHandler documentHandler; - - public LuceneEntityIndexBuilder(IndexWriter indexWriter, ISearchService searchService, ILuceneDocumentHandler documentHandler, ILogger logger) { - this.indexWriter = indexWriter; - this.searchService = searchService; - this.documentHandler = documentHandler; - this.logger = logger; - } - - public void BuildIndex() { - logger.Info("Building lucene index"); - foreach (var quote in searchService.GetAllIndexableRecords()) { - indexWriter.AddDocument(documentHandler.BuildDocument(quote)); - } - - indexWriter.Optimize(); - indexWriter.Commit(); - logger.Info("Finished building lucene index"); - } - - public void UpdateIndex(T entity) { - if (entity.IsTransient()) { - throw new SearchIndexException(string.Format("Cannot add a transient entity to the index ({0})", entity)); - } - - logger.Info(string.Format("Updating index for {0}", entity)); - //delete current document, if it exists - indexWriter.DeleteDocuments(documentHandler.GetIdTerm(entity)); - indexWriter.AddDocument(documentHandler.BuildDocument(entity)); - - indexWriter.Commit(); - logger.Info(string.Format("Finished updating index for {0}", entity)); - } - } -} \ No newline at end of file diff --git a/Src/VideoGameQuotes.Api/Search/Lucene/LuceneEntitySearcher.cs b/Src/VideoGameQuotes.Api/Search/Lucene/LuceneEntitySearcher.cs deleted file mode 100644 index 39b8d44..0000000 --- a/Src/VideoGameQuotes.Api/Search/Lucene/LuceneEntitySearcher.cs +++ /dev/null @@ -1,50 +0,0 @@ -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(); - } - } - } -} \ No newline at end of file diff --git a/Src/VideoGameQuotes.Api/Search/Lucene/LuceneExtensions.cs b/Src/VideoGameQuotes.Api/Search/Lucene/LuceneExtensions.cs deleted file mode 100644 index 533e73c..0000000 --- a/Src/VideoGameQuotes.Api/Search/Lucene/LuceneExtensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Collections.Generic; -using Lucene.Net.Search; - -namespace VideoGameQuotes.Api.Search.Lucene { - public static class LuceneExtensions { - public static IEnumerable ToEnumerable(this Hits hits) { - var iterator = hits.Iterator(); - while (iterator.MoveNext()) { - yield return (Hit)iterator.Current; - } - } - } -} \ No newline at end of file diff --git a/Src/VideoGameQuotes.Api/Search/Lucene/LuceneQuoteSearcher.cs b/Src/VideoGameQuotes.Api/Search/Lucene/LuceneQuoteSearcher.cs deleted file mode 100644 index 8f73536..0000000 --- a/Src/VideoGameQuotes.Api/Search/Lucene/LuceneQuoteSearcher.cs +++ /dev/null @@ -1,62 +0,0 @@ -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; - } - } -} \ No newline at end of file diff --git a/Src/VideoGameQuotes.Api/Search/SearchIndexException.cs b/Src/VideoGameQuotes.Api/Search/SearchIndexException.cs deleted file mode 100644 index ad275c4..0000000 --- a/Src/VideoGameQuotes.Api/Search/SearchIndexException.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace VideoGameQuotes.Api.Search { - /// - /// Raised when an error occurs while reading/writing a search index - /// - public class SearchIndexException : Exception { - public SearchIndexException(string message = null, Exception innerException = null) : base(message, innerException) { } - } -} \ No newline at end of file diff --git a/Src/VideoGameQuotes.Api/Search/SearchResult.cs b/Src/VideoGameQuotes.Api/Search/SearchResult.cs deleted file mode 100644 index 1605de8..0000000 --- a/Src/VideoGameQuotes.Api/Search/SearchResult.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace VideoGameQuotes.Api.Search { - /// - /// Represents a search result - /// - public class SearchResult { - /// - /// A value (between 0 and 1, the higher the better) representing how good - /// the match is between the search query and the value - /// - public double Score { get; set; } - - /// - /// The matched quote - /// - public T Entity { get; set; } - } -} \ No newline at end of file diff --git a/Src/VideoGameQuotes.Api/VideoGameQuotes.Api.csproj b/Src/VideoGameQuotes.Api/VideoGameQuotes.Api.csproj index 409d4a8..2d55f47 100644 --- a/Src/VideoGameQuotes.Api/VideoGameQuotes.Api.csproj +++ b/Src/VideoGameQuotes.Api/VideoGameQuotes.Api.csproj @@ -37,9 +37,6 @@ ..\..\Lib\log4net.dll - - ..\..\Lib\Lucene.Net.dll - ..\..\Lib\MySql.Data.dll @@ -69,13 +66,6 @@ - - - - - - - @@ -85,9 +75,6 @@ - - - diff --git a/Src/VideoGameQuotes.Web/Configuration/UpdateSearchIndexCallHandler.cs b/Src/VideoGameQuotes.Web/Configuration/UpdateSearchIndexCallHandler.cs index 9f1e141..b655e3b 100644 --- a/Src/VideoGameQuotes.Web/Configuration/UpdateSearchIndexCallHandler.cs +++ b/Src/VideoGameQuotes.Web/Configuration/UpdateSearchIndexCallHandler.cs @@ -4,8 +4,8 @@ using System.Reflection; using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.InterceptionExtension; using Portoa.Persistence; +using Portoa.Search; using VideoGameQuotes.Api; -using VideoGameQuotes.Api.Search; namespace VideoGameQuotes.Web.Configuration { diff --git a/Src/VideoGameQuotes.Web/Controllers/QuoteController.cs b/Src/VideoGameQuotes.Web/Controllers/QuoteController.cs index e5ef905..c07ef69 100644 --- a/Src/VideoGameQuotes.Web/Controllers/QuoteController.cs +++ b/Src/VideoGameQuotes.Web/Controllers/QuoteController.cs @@ -1,15 +1,14 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Net; using System.Web.Mvc; using Portoa.Persistence; +using Portoa.Search; using Portoa.Validation.DataAnnotations; using Portoa.Web; using Portoa.Web.Controllers; using Portoa.Web.Results; using VideoGameQuotes.Api; -using VideoGameQuotes.Api.Search; using VideoGameQuotes.Web.Models; using VideoGameQuotes.Web.Security; using VideoGameQuotes.Web.Services; diff --git a/Src/VideoGameQuotes.Web/Global.asax.cs b/Src/VideoGameQuotes.Web/Global.asax.cs index facc9b5..390a4ab 100644 --- a/Src/VideoGameQuotes.Web/Global.asax.cs +++ b/Src/VideoGameQuotes.Web/Global.asax.cs @@ -13,7 +13,9 @@ using Lucene.Net.Util; using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.InterceptionExtension; using Portoa.Logging; +using Portoa.Lucene; using Portoa.Persistence; +using Portoa.Search; using Portoa.Web; using Portoa.Web.Models; using Portoa.Web.Security; @@ -21,11 +23,10 @@ using Portoa.Web.Unity; using UnityGenerics; using VideoGameQuotes.Api; using VideoGameQuotes.Api.Persistence; -using VideoGameQuotes.Api.Search; -using VideoGameQuotes.Api.Search.Lucene; using VideoGameQuotes.Web.Configuration; using VideoGameQuotes.Web.Controllers; using VideoGameQuotes.Web.Models; +using VideoGameQuotes.Web.Search; using VideoGameQuotes.Web.Security; using VideoGameQuotes.Web.Services; using Directory = Lucene.Net.Store.Directory; diff --git a/Src/VideoGameQuotes.Web/Models/SearchModel.cs b/Src/VideoGameQuotes.Web/Models/SearchModel.cs index e178701..de69021 100644 --- a/Src/VideoGameQuotes.Web/Models/SearchModel.cs +++ b/Src/VideoGameQuotes.Web/Models/SearchModel.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; +using Portoa.Search; using VideoGameQuotes.Api; -using VideoGameQuotes.Api.Search; namespace VideoGameQuotes.Web.Models { public class SearchModel { diff --git a/Src/VideoGameQuotes.Api/Search/Lucene/QuoteDocumentHandler.cs b/Src/VideoGameQuotes.Web/Search/QuoteDocumentHandler.cs similarity index 82% rename from Src/VideoGameQuotes.Api/Search/Lucene/QuoteDocumentHandler.cs rename to Src/VideoGameQuotes.Web/Search/QuoteDocumentHandler.cs index 87c7354..eefcb08 100644 --- a/Src/VideoGameQuotes.Api/Search/Lucene/QuoteDocumentHandler.cs +++ b/Src/VideoGameQuotes.Web/Search/QuoteDocumentHandler.cs @@ -1,9 +1,10 @@ using Lucene.Net.Documents; using Lucene.Net.Index; +using Portoa.Lucene; +using VideoGameQuotes.Api; -namespace VideoGameQuotes.Api.Search.Lucene { +namespace VideoGameQuotes.Web.Search { public class QuoteDocumentHandler : ILuceneDocumentHandler { - public Document BuildDocument(Quote quote) { var document = new Document(); document.Add(new Field("id", quote.Id.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED)); diff --git a/Src/VideoGameQuotes.Api/Persistence/SearchService.cs b/Src/VideoGameQuotes.Web/Search/SearchService.cs similarity index 70% rename from Src/VideoGameQuotes.Api/Persistence/SearchService.cs rename to Src/VideoGameQuotes.Web/Search/SearchService.cs index d54b9c6..e442451 100644 --- a/Src/VideoGameQuotes.Api/Persistence/SearchService.cs +++ b/Src/VideoGameQuotes.Web/Search/SearchService.cs @@ -1,13 +1,9 @@ using System.Collections.Generic; using System.Linq; using Portoa.Persistence; +using Portoa.Search; -namespace VideoGameQuotes.Api.Persistence { - - public interface ISearchService where T : Entity { - IEnumerable FindByIds(IEnumerable ids); - IEnumerable GetAllIndexableRecords(); - } +namespace VideoGameQuotes.Web.Search { public class SearchService : ISearchService where T : Entity { private readonly IRepository repository; @@ -18,7 +14,6 @@ namespace VideoGameQuotes.Api.Persistence { [UnitOfWork] public IEnumerable FindByIds(IEnumerable ids) { - return repository .Records .Where(entity => ids.ToArray().Contains(entity.Id)); diff --git a/Src/VideoGameQuotes.Web/VideoGameQuotes.Web.csproj b/Src/VideoGameQuotes.Web/VideoGameQuotes.Web.csproj index a3c553c..aa1bd91 100644 --- a/Src/VideoGameQuotes.Web/VideoGameQuotes.Web.csproj +++ b/Src/VideoGameQuotes.Web/VideoGameQuotes.Web.csproj @@ -49,6 +49,7 @@ ..\..\Lib\Portoa.Log4Net.dll + False ..\..\Lib\Portoa.NHibernate.dll @@ -57,8 +58,6 @@ ..\..\Lib\Portoa.Web.dll - - @@ -68,23 +67,15 @@ 3.5 - - 3.5 - - - 3.5 - 3.5 - - ..\..\Lib\UnityGenerics.dll @@ -101,6 +92,8 @@ + + diff --git a/Src/VideoGameQuotes.Web/Views/Quote/Search.aspx b/Src/VideoGameQuotes.Web/Views/Quote/Search.aspx index d3f1d6f..8f16979 100644 --- a/Src/VideoGameQuotes.Web/Views/Quote/Search.aspx +++ b/Src/VideoGameQuotes.Web/Views/Quote/Search.aspx @@ -8,7 +8,7 @@ <% foreach (var result in Model.Results) { - Html.RenderPartial("SingleQuote", new QuoteModel {Quote = result.Entity, User = Model.User }); + Html.RenderPartial("SingleQuote", new QuoteModel { Quote = result.Record, User = Model.User }); } %> \ No newline at end of file