public ActionResult Search(string query, int? page, string titlesonly) { var pageNumber = page ?? 1; if (pageNumber <= 0) pageNumber = 1; var q = new SearchQuery { Query = query, CurrentPage = pageNumber, TitlesOnly = !string.IsNullOrWhiteSpace(titlesonly), }; var vm = new SearchResultsViewModel {Query = q, SearchResults = new List<SearchResultsViewModel.SearchResult>(), TotalResults = 0}; try { vm = Core.Index.SearchWithSuggestions(q); } catch (ParseException ex) { ViewBag.ErrorMessage = "Error: " + ex.Message; } ViewBag.Query = q; return View(vm); }
public static SearchResultsViewModel SearchWithSuggestions(SearchQuery searchQuery, bool suggestOnlyWhenNoResults = false) { var ret = new SearchResultsViewModel { SearchResults = new List<SearchResultsViewModel.SearchResult>(PageSize), Query = searchQuery }; // Parse query, possibly throwing a ParseException Query query; if (searchQuery.TitlesOnly) { var qp = new QueryParser(Lucene.Net.Util.Version.LUCENE_29, "Title", new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29) ); query = qp.Parse(searchQuery.Query); } else { query = MultiFieldQueryParser.Parse(Lucene.Net.Util.Version.LUCENE_29, searchQuery.Query, SearchFields, SearchFlags, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29) ); } // Perform the actual search var tsdc = TopScoreDocCollector.create(PageSize * searchQuery.CurrentPage, true); Searcher.Search(query, tsdc); ret.TotalResults = tsdc.GetTotalHits(); var hits = tsdc.TopDocs().ScoreDocs; // Do the suggestion magic if (suggestOnlyWhenNoResults && ret.TotalResults == 0 || (!suggestOnlyWhenNoResults)) { ret.Suggestions = new List<string>(); var spellChecker = new SpellChecker.Net.Search.Spell.SpellChecker(Searcher.GetIndexReader().Directory()); // This is kind of a hack to get things working quickly // for real-world usage we probably want to get the analyzed terms from the Query object var individualTerms = searchQuery.Query.Split(new[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (var term in individualTerms) { // we only specify field name if we actually got results, // to improve suggestions relevancy ret.Suggestions.AddRange(spellChecker.SuggestSimilar(term, searchQuery.MaxSuggestions, null, ret.TotalResults == 0 ? null : "Title", true)); } } // Init the highlighter instance var fvh = new FastVectorHighlighter(FastVectorHighlighter.DEFAULT_PHRASE_HIGHLIGHT, FastVectorHighlighter.DEFAULT_FIELD_MATCH, new SimpleFragListBuilder(), new ScoreOrderFragmentsBuilder(new[] { "[b]" }, new[] { "[/b]" })); int i; for (i = (searchQuery.CurrentPage - 1) * PageSize; i < hits.Length; ++i) { var d = Searcher.Doc(hits[i].doc); var fq = fvh.GetFieldQuery(query); var fragment = fvh.GetBestFragment(fq, Searcher.GetIndexReader(), hits[i].doc, "Content", 400); ret.SearchResults.Add(new SearchResultsViewModel.SearchResult { Id = d.Get("Id"), Title = d.Get("Title"), Score = hits[i].score, LuceneDocId = hits[i].doc, Fragment = MvcHtmlString.Create(fragment.HtmlStripFragment()), }); } return ret; }
public static SearchResultsViewModel Search(SearchQuery searchQuery) { var ret = new SearchResultsViewModel { SearchResults = new List<SearchResultsViewModel.SearchResult>(PageSize), Query = searchQuery }; // Parse query, possibly throwing a ParseException Query query; if (searchQuery.TitlesOnly) // we only need to query on one field { var qp = new QueryParser(Lucene.Net.Util.Version.LUCENE_29, "Title", new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29)); query = qp.Parse(searchQuery.Query); } else // querying on both fields, Content and Title { query = MultiFieldQueryParser.Parse(Lucene.Net.Util.Version.LUCENE_29, searchQuery.Query, SearchFields, SearchFlags, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29) ); } // Init the highlighter instance var fvh = new FastVectorHighlighter(FastVectorHighlighter.DEFAULT_PHRASE_HIGHLIGHT, FastVectorHighlighter.DEFAULT_FIELD_MATCH, new SimpleFragListBuilder(), new ScoreOrderFragmentsBuilder(new[] { "[b]" }, new[] { "[/b]" }) ); // Perform the actual search var tsdc = TopScoreDocCollector.create(PageSize * searchQuery.CurrentPage, true); Searcher.Search(query, tsdc); ret.TotalResults = tsdc.GetTotalHits(); var hits = tsdc.TopDocs().ScoreDocs; int i; for (i = (searchQuery.CurrentPage - 1) * PageSize; i < hits.Length; ++i) { var d = Searcher.Doc(hits[i].doc); var fq = fvh.GetFieldQuery(query); var fragment = fvh.GetBestFragment(fq, Searcher.GetIndexReader(), hits[i].doc, "Content", 400); ret.SearchResults.Add(new SearchResultsViewModel.SearchResult { Id = d.Get("Id"), Title = d.Get("Title"), Score = hits[i].score, LuceneDocId = hits[i].doc, Fragment = MvcHtmlString.Create(fragment.HtmlStripFragment()), }); } return ret; }