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 }