3 // SearchableIndex.cs: Index that uses Lucene to search through the docs
5 // Author: Mario Sopena
10 using System.Collections;
12 using Lucene.Net.Index;
13 using Lucene.Net.Documents;
14 using Lucene.Net.Analysis;
15 using Lucene.Net.Analysis.Standard;
16 using Lucene.Net.Search;
17 using Lucene.Net.QueryParsers;
18 using Lucene.Net.Store;
22 public class SearchableIndex
24 const int maxSearchCount = 30;
26 IndexSearcher searcher;
30 if (dir == null) dir = "search_index";
35 public ArrayList Results;
37 public static SearchableIndex Load (string dir) {
38 SearchableIndex s = new SearchableIndex ();
40 s.Results = new ArrayList (20);
42 //s.searcher = new IndexSearcher (dir);
43 // TODO: parametrize that depending if we run on the desktop (low footprint) or the server (use RAMDirectory for instance)
44 s.searcher = new IndexSearcher (FSDirectory.Open (dir));
45 } catch (IOException) {
46 Console.WriteLine ("Index nonexistent or in bad format");
53 // Search the index with term
56 public Result Search (string term)
58 return Search (term, maxSearchCount);
61 public Result Search (string term, int count)
63 return Search (term, count, 0);
66 public Result Search (string term, int count, int start) {
68 term = term.ToLower ();
69 Term htTerm = new Term ("hottext", term);
70 Query qq1 = new FuzzyQuery (htTerm);
71 Query qq2 = new TermQuery (htTerm);
73 Query qq3 = new PrefixQuery (htTerm);
75 DisjunctionMaxQuery q1 = new DisjunctionMaxQuery (0f);
79 Query q2 = new TermQuery (new Term ("text", term));
81 Query q3 = new TermQuery (new Term ("examples", term));
83 DisjunctionMaxQuery q = new DisjunctionMaxQuery (0f);
89 TopDocs top = SearchInternal (q, count, start);
90 Result r = new Result (term, searcher, top.ScoreDocs);
93 } catch (IOException) {
94 Console.WriteLine ("No index in {0}", dir);
99 TopDocs SearchInternal (Query q, int count, int start)
101 // Easy path that doesn't involve creating a Collector ourselves
102 // watch for Lucene.NET improvement on that (like searcher.SearchAfter)
104 return searcher.Search (q, count);
106 var weight = searcher.CreateWeight (q); // TODO: reuse weight instead of query
107 var collector = TopScoreDocCollector.Create (start + count + 1, false);
108 searcher.Search (q, collector);
110 return collector.TopDocs (start, count);
113 public Result FastSearch (string term, int number)
116 term = term.ToLower ();
117 Query q1 = new TermQuery (new Term ("hottext", term));
118 Query q2 = new PrefixQuery (new Term ("hottext", term));
120 DisjunctionMaxQuery q = new DisjunctionMaxQuery (0f);
123 TopDocs top = searcher.Search (q, number);
124 return new Result (term, searcher, top.ScoreDocs);
125 } catch (IOException) {
126 Console.WriteLine ("No index in {0}", dir);
131 Query Parse (string term, string field, bool fuzzy)
133 QueryParser parser = new QueryParser (Lucene.Net.Util.Version.LUCENE_CURRENT,
135 new StandardAnalyzer (Lucene.Net.Util.Version.LUCENE_CURRENT));
136 return parser.Parse (term);
140 // An object representing the search term with the results
142 public class Result {
152 get { return docs.Length; }
155 public Document this [int i] {
156 get { return searcher.Doc (docs[i].Doc); }
159 public string GetTitle (int i)
161 Document d = this[i];
162 return d == null ? string.Empty : d.Get ("title");
165 public string GetUrl (int i)
167 Document d = this[i];
168 return d == null ? string.Empty : d.Get ("url");
171 public string GetFullTitle (int i)
173 Document d = this[i];
174 return d == null ? string.Empty : d.Get ("fulltitle");
177 public float Score (int i)
179 return docs[i].Score;
182 public Result (string Term, Searcher searcher, ScoreDoc[] docs)
185 this.searcher = searcher;