Add autoconf checks for platforms without IPv6
[mono.git] / mcs / class / monodoc / Monodoc / SearchableIndex.cs
1 //
2 //
3 // SearchableIndex.cs: Index that uses Lucene to search through the docs 
4 //
5 // Author: Mario Sopena
6 //
7
8 using System;
9 using System.IO;
10 using System.Collections.Generic;
11 // Lucene imports
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;
19
20 namespace Monodoc
21 {
22         public class SearchableIndex 
23         {
24                 const int maxSearchCount = 30;
25
26                 IndexSearcher searcher;
27                 string dir;
28
29                 public string Dir {
30                         get { 
31                                 if (dir == null)
32                                         dir = "search_index";
33                                 return dir;
34                         }
35                         set { dir = value; }
36                 }
37
38                 public static SearchableIndex Load (string dir)
39                 {
40                         SearchableIndex s = new SearchableIndex ();
41                         s.dir = dir;
42                         try {
43                                 //s.searcher = new IndexSearcher (dir);
44                                 // TODO: parametrize that depending if we run on the desktop (low footprint) or the server (use RAMDirectory for instance)
45                                 s.searcher = new IndexSearcher (FSDirectory.Open (dir));
46                         } catch (IOException) {
47                                 Console.WriteLine ("Index nonexistent or in bad format");
48                                 return null;
49                         }
50                         return s;
51                 }
52                 
53                 public Result Search (string term)
54                 {
55                         return Search (term, maxSearchCount);
56                 }
57
58                 public Result Search (string term, int count)
59                 {
60                         return Search (term, count, 0);
61                 }
62
63                 public Result Search (string term, int count, int start) {
64                         try {
65                                 term = term.ToLower ();
66                                 Term htTerm = new Term ("hottext", term);
67                                 Query qq1 = new FuzzyQuery (htTerm);
68                                 Query qq2 = new TermQuery (htTerm);
69                                 qq2.Boost = 10f;
70                                 Query qq3 = new PrefixQuery (htTerm);
71                                 qq3.Boost = 10f;
72                                 DisjunctionMaxQuery q1 = new DisjunctionMaxQuery (0f);
73                                 q1.Add (qq1);
74                                 q1.Add (qq2);
75                                 q1.Add (qq3);
76                                 Query q2 = new TermQuery (new Term ("text", term));
77                                 q2.Boost = 3f;
78                                 Query q3 = new TermQuery (new Term ("examples", term));
79                                 q3.Boost = 3f;
80                                 DisjunctionMaxQuery q = new DisjunctionMaxQuery (0f);
81
82                                 q.Add (q1);
83                                 q.Add (q2);
84                                 q.Add (q3);
85                         
86                                 TopDocs top = SearchInternal (q, count, start);
87                                 Result r = new Result (term, searcher, top.ScoreDocs);
88                                 return r;
89                         } catch (IOException) {
90                                 Console.WriteLine ("No index in {0}", dir);
91                                 return null;
92                         }
93                 }
94
95                 TopDocs SearchInternal (Query q, int count, int start)
96                 {
97                         // Easy path that doesn't involve creating a Collector ourselves
98                         // watch for Lucene.NET improvement on that (like searcher.SearchAfter)
99                         if (start == 0)
100                                 return searcher.Search (q, count);
101
102                         var weight = searcher.CreateWeight (q); // TODO: reuse weight instead of query
103                         var collector = TopScoreDocCollector.Create (start + count + 1, false);
104                         searcher.Search (q, collector);
105
106                         return collector.TopDocs (start, count);
107                 }
108
109                 public Result FastSearch (string term, int number)
110                 {
111                         try {
112                                 term = term.ToLower ();
113                                 Query q1 = new TermQuery (new Term ("hottext", term));
114                                 Query q2 = new PrefixQuery (new Term ("hottext", term));
115                                 q2.Boost = 0.5f;
116                                 DisjunctionMaxQuery q = new DisjunctionMaxQuery (0f);
117                                 q.Add (q1);
118                                 q.Add (q2);
119                                 TopDocs top = searcher.Search (q, number);
120                                 return new Result (term, searcher, top.ScoreDocs);
121                         } catch (IOException) {
122                                 Console.WriteLine ("No index in {0}", dir);
123                                 return null;
124                         }
125                 }
126         }
127
128         //
129         // An object representing the search term with the results
130         // 
131         public class Result {
132                 string term;
133                 Searcher searcher;
134                 ScoreDoc[] docs;
135
136                 public string Term {
137                         get { return term;}
138                 }
139
140                 public int Count {
141                         get { return docs.Length; }
142                 }
143
144                 public Document this [int i] {
145                         get { return searcher.Doc (docs[i].Doc); }
146                 }
147         
148                 public string GetTitle (int i) 
149                 {
150                         Document d = this[i];
151                         return d == null ? string.Empty : d.Get ("title");
152                 }
153
154                 public string GetUrl (int i)
155                 {
156                         Document d = this[i];
157                         return d == null ? string.Empty : d.Get ("url");
158                 }
159
160                 public string GetFullTitle (int i)
161                 {
162                         Document d = this[i];
163                         return d == null ? string.Empty : d.Get ("fulltitle");
164                 }
165
166                 public float Score (int i)
167                 {
168                         return docs[i].Score;
169                 }
170
171                 public Result (string Term, Searcher searcher, ScoreDoc[] docs) 
172                 {
173                         this.term = Term;
174                         this.searcher = searcher;
175                         this.docs = docs;
176                 }
177         }
178 }
179