Mercurial Hosting > luan
comparison lucene/src/luan/modules/lucene/LuceneSearcher.java @ 232:9ce18106f95a
more lucene work
git-svn-id: https://luan-java.googlecode.com/svn/trunk@233 21e917c8-12df-6dd8-5cb6-c86387c605b9
author | fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9> |
---|---|
date | Wed, 01 Oct 2014 06:55:14 +0000 |
parents | 4438cb2e04d0 |
children | ef39bc4d3f70 |
comparison
equal
deleted
inserted
replaced
231:a35417bf493a | 232:9ce18106f95a |
---|---|
1 package luan.modules.lucene; | 1 package luan.modules.lucene; |
2 | 2 |
3 import java.io.IOException; | 3 import java.io.IOException; |
4 import java.util.Iterator; | |
5 import java.util.NoSuchElementException; | 4 import java.util.NoSuchElementException; |
5 import java.util.Map; | |
6 import java.util.List; | |
6 import org.apache.lucene.index.IndexReader; | 7 import org.apache.lucene.index.IndexReader; |
7 import org.apache.lucene.document.Document; | 8 import org.apache.lucene.index.Term; |
8 import org.apache.lucene.search.IndexSearcher; | 9 import org.apache.lucene.search.IndexSearcher; |
9 import org.apache.lucene.search.Query; | 10 import org.apache.lucene.search.Query; |
10 import org.apache.lucene.search.TopDocs; | 11 import org.apache.lucene.search.TopDocs; |
11 import org.apache.lucene.search.TopFieldDocs; | 12 import org.apache.lucene.search.TopFieldDocs; |
12 import org.apache.lucene.search.Sort; | 13 import org.apache.lucene.search.Sort; |
14 import org.apache.lucene.search.SortField; | |
13 import org.apache.lucene.search.ScoreDoc; | 15 import org.apache.lucene.search.ScoreDoc; |
16 import org.apache.lucene.search.TermQuery; | |
17 import org.apache.lucene.search.BooleanQuery; | |
18 import org.apache.lucene.search.BooleanClause; | |
19 import luan.Luan; | |
20 import luan.LuanState; | |
14 import luan.LuanTable; | 21 import luan.LuanTable; |
22 import luan.LuanFunction; | |
23 import luan.LuanJavaFunction; | |
24 import luan.LuanException; | |
15 | 25 |
16 | 26 |
17 public final class LuceneSearcher { | 27 public final class LuceneSearcher { |
18 private final IndexSearcher searcher; | 28 private final IndexSearcher searcher; |
19 | 29 |
20 LuceneSearcher(IndexReader reader) { | 30 LuceneSearcher(IndexReader reader) { |
21 this.searcher = new IndexSearcher(reader); | 31 this.searcher = new IndexSearcher(reader); |
22 } | 32 } |
23 | 33 |
24 // call in finally block | 34 // call in finally block |
25 public void close() { | 35 void close() { |
26 try { | 36 try { |
27 searcher.getIndexReader().decRef(); | 37 searcher.getIndexReader().decRef(); |
28 } catch(IOException e) { | 38 } catch(IOException e) { |
29 throw new RuntimeException(e); | 39 throw new RuntimeException(e); |
30 } | 40 } |
31 } | 41 } |
32 | 42 |
33 private Document rawDoc(int docID) { | 43 public LuanTable doc(int docID) throws IOException { |
44 return LuceneDocument.toTable(searcher.doc(docID)); | |
45 } | |
46 | |
47 TopDocs search(Query query,int n) throws IOException { | |
48 return searcher.search(query,n); | |
49 } | |
50 | |
51 TopFieldDocs search(Query query,int n,Sort sort) throws IOException { | |
52 return searcher.search(query,n,sort); | |
53 } | |
54 | |
55 // luan | |
56 | |
57 private Query termQuery(Map<Object,Object> map) { | |
58 if( map.size() != 1 ) | |
59 return null; | |
60 Map.Entry<Object,Object> entry = map.entrySet().iterator().next(); | |
61 Object key = entry.getKey(); | |
62 Object value = entry.getValue(); | |
63 if( key instanceof String && value instanceof String ) { | |
64 return new TermQuery(new Term( (String)key, (String)value )); | |
65 } | |
66 return null; | |
67 } | |
68 | |
69 private Query booleanQuery(Map<Object,Object> map) { | |
70 BooleanQuery query = new BooleanQuery(); | |
71 for( Map.Entry<Object,Object> entry : map.entrySet() ) { | |
72 Object key = entry.getKey(); | |
73 Object value = entry.getValue(); | |
74 if( !(key instanceof String && value instanceof LuanTable) ) | |
75 return null; | |
76 Query subQuery = query( (LuanTable)value ); | |
77 if( subQuery == null ) | |
78 return null; | |
79 BooleanClause.Occur occur; | |
80 try { | |
81 occur = BooleanClause.Occur.valueOf( ((String)key).toUpperCase() ); | |
82 } catch(IllegalArgumentException e) { | |
83 return null; | |
84 } | |
85 query.add(subQuery,occur); | |
86 } | |
87 return query; | |
88 } | |
89 | |
90 private Query query(LuanTable queryTbl) { | |
91 Map<Object,Object> map = queryTbl.asMap(); | |
92 if( map.isEmpty() ) | |
93 return null; | |
94 Query query; | |
95 query = termQuery(map); if(query!=null) return query; | |
96 query = booleanQuery(map); if(query!=null) return query; | |
97 return null; | |
98 } | |
99 | |
100 private SortField sortField(LuanState luan,List<Object> list,String pos) throws LuanException { | |
101 int size = list.size(); | |
102 if( size < 2 || size > 3 ) | |
103 throw luan.exception("invalid sort field"+pos); | |
104 Object obj0 = list.get(0); | |
105 Object obj1 = list.get(1); | |
106 if( !(obj0 instanceof String && obj1 instanceof String) ) | |
107 throw luan.exception("invalid sort field"+pos); | |
108 String field = (String)obj0; | |
109 SortField.Type type; | |
34 try { | 110 try { |
35 return searcher.doc(docID); | 111 type = SortField.Type.valueOf( ((String)obj1).toUpperCase() ); |
36 } catch(IOException e) { | 112 } catch(IllegalArgumentException e) { |
113 throw luan.exception("invalid sort field type"+pos); | |
114 } | |
115 if( size == 2 ) | |
116 return new SortField(field,type); | |
117 Object obj2 = list.get(2); | |
118 if( !(obj2 instanceof Boolean) ) | |
119 throw luan.exception("invalid sort field"+pos+", 'reverse' must be boolean"); | |
120 boolean reverse = (Boolean)obj2; | |
121 return new SortField(field,type,reverse); | |
122 } | |
123 | |
124 private Sort sort(LuanState luan,LuanTable sortTbl) throws LuanException { | |
125 if( !sortTbl.isList() ) | |
126 throw luan.exception("invalid sort, must be list"); | |
127 List<Object> list = sortTbl.asList(); | |
128 if( list.isEmpty() ) | |
129 throw luan.exception("sort cannot be empty"); | |
130 if( list.get(0) instanceof String ) | |
131 return new Sort(sortField(luan,list,"")); | |
132 SortField[] flds = new SortField[list.size()]; | |
133 for( int i=0; i<flds.length; i++ ) { | |
134 Object obj = list.get(i); | |
135 if( !(obj instanceof LuanTable) ) | |
136 throw luan.exception("invalid sort parameter at position "+(i+1)); | |
137 LuanTable fldTbl = (LuanTable)obj; | |
138 if( !fldTbl.isList() ) | |
139 throw luan.exception("invalid sort field at position "+(i+1)+", must be list"); | |
140 flds[i] = sortField(luan,fldTbl.asList()," at position "+(i+1)); | |
141 } | |
142 return new Sort(flds); | |
143 } | |
144 | |
145 public Object[] search( LuanState luan, LuanTable queryTbl, int n, LuanTable sortTbl ) throws LuanException, IOException { | |
146 Query query = query(queryTbl); | |
147 if( query == null ) | |
148 throw luan.exception("invalid query"); | |
149 TopDocs td = sortTbl==null ? searcher.search(query,n) : searcher.search(query,n,sort(luan,sortTbl)); | |
150 final ScoreDoc[] scoreDocs = td.scoreDocs; | |
151 LuanFunction results = new LuanFunction() { | |
152 int i = 0; | |
153 | |
154 @Override public Object call(LuanState luan,Object[] args) throws LuanException { | |
155 if( i >= scoreDocs.length ) | |
156 return LuanFunction.NOTHING; | |
157 try { | |
158 LuanTable doc = doc(scoreDocs[i++].doc); | |
159 return doc; | |
160 } catch(IOException e) { | |
161 throw luan.exception(e); | |
162 } | |
163 } | |
164 }; | |
165 return new Object[]{ results, scoreDocs.length, td.totalHits }; | |
166 } | |
167 | |
168 private void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException { | |
169 t.put( method, new LuanJavaFunction(LuceneSearcher.class.getMethod(method,parameterTypes),this) ); | |
170 } | |
171 | |
172 LuanTable table() { | |
173 LuanTable tbl = Luan.newTable(); | |
174 try { | |
175 add( tbl, "search", LuanState.class, LuanTable.class, Integer.TYPE, LuanTable.class ); | |
176 } catch(NoSuchMethodException e) { | |
37 throw new RuntimeException(e); | 177 throw new RuntimeException(e); |
38 } | 178 } |
179 return tbl; | |
39 } | 180 } |
40 | 181 |
41 public LuanTable doc(int docID) { | |
42 return LuceneDocument.toTable(rawDoc(docID)); | |
43 } | |
44 | |
45 public TopDocs search(Query query,int n) { | |
46 try { | |
47 return searcher.search(query,n); | |
48 } catch(IOException e) { | |
49 throw new RuntimeException(e); | |
50 } | |
51 } | |
52 | |
53 public TopFieldDocs search(Query query,int n,Sort sort) { | |
54 try { | |
55 return searcher.search(query,n,sort); | |
56 } catch(IOException e) { | |
57 throw new RuntimeException(e); | |
58 } | |
59 } | |
60 | |
61 public Iterable<LuanTable> docs(TopDocs td) { | |
62 final ScoreDoc[] scoreDocs = td.scoreDocs; | |
63 return new Iterable<LuanTable>() { | |
64 public Iterator<LuanTable> iterator() { | |
65 return new Iterator<LuanTable>() { | |
66 private int i = 0; | |
67 | |
68 public boolean hasNext() { | |
69 return i < scoreDocs.length; | |
70 } | |
71 | |
72 public LuanTable next() { | |
73 if( !hasNext() ) | |
74 throw new NoSuchElementException(); | |
75 return doc(scoreDocs[i++].doc); | |
76 } | |
77 | |
78 public void remove() { | |
79 throw new UnsupportedOperationException(); | |
80 } | |
81 }; | |
82 } | |
83 }; | |
84 } | |
85 } | 182 } |