Mercurial Hosting > luan
diff 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 |
line wrap: on
line diff
--- a/lucene/src/luan/modules/lucene/LuceneSearcher.java Wed Oct 01 02:15:39 2014 +0000 +++ b/lucene/src/luan/modules/lucene/LuceneSearcher.java Wed Oct 01 06:55:14 2014 +0000 @@ -1,17 +1,27 @@ package luan.modules.lucene; import java.io.IOException; -import java.util.Iterator; import java.util.NoSuchElementException; +import java.util.Map; +import java.util.List; import org.apache.lucene.index.IndexReader; -import org.apache.lucene.document.Document; +import org.apache.lucene.index.Term; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.TopDocs; import org.apache.lucene.search.TopFieldDocs; import org.apache.lucene.search.Sort; +import org.apache.lucene.search.SortField; import org.apache.lucene.search.ScoreDoc; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.BooleanClause; +import luan.Luan; +import luan.LuanState; import luan.LuanTable; +import luan.LuanFunction; +import luan.LuanJavaFunction; +import luan.LuanException; public final class LuceneSearcher { @@ -22,7 +32,7 @@ } // call in finally block - public void close() { + void close() { try { searcher.getIndexReader().decRef(); } catch(IOException e) { @@ -30,56 +40,143 @@ } } - private Document rawDoc(int docID) { - try { - return searcher.doc(docID); - } catch(IOException e) { - throw new RuntimeException(e); + public LuanTable doc(int docID) throws IOException { + return LuceneDocument.toTable(searcher.doc(docID)); + } + + TopDocs search(Query query,int n) throws IOException { + return searcher.search(query,n); + } + + TopFieldDocs search(Query query,int n,Sort sort) throws IOException { + return searcher.search(query,n,sort); + } + + // luan + + private Query termQuery(Map<Object,Object> map) { + if( map.size() != 1 ) + return null; + Map.Entry<Object,Object> entry = map.entrySet().iterator().next(); + Object key = entry.getKey(); + Object value = entry.getValue(); + if( key instanceof String && value instanceof String ) { + return new TermQuery(new Term( (String)key, (String)value )); } + return null; } - public LuanTable doc(int docID) { - return LuceneDocument.toTable(rawDoc(docID)); + private Query booleanQuery(Map<Object,Object> map) { + BooleanQuery query = new BooleanQuery(); + for( Map.Entry<Object,Object> entry : map.entrySet() ) { + Object key = entry.getKey(); + Object value = entry.getValue(); + if( !(key instanceof String && value instanceof LuanTable) ) + return null; + Query subQuery = query( (LuanTable)value ); + if( subQuery == null ) + return null; + BooleanClause.Occur occur; + try { + occur = BooleanClause.Occur.valueOf( ((String)key).toUpperCase() ); + } catch(IllegalArgumentException e) { + return null; + } + query.add(subQuery,occur); + } + return query; + } + + private Query query(LuanTable queryTbl) { + Map<Object,Object> map = queryTbl.asMap(); + if( map.isEmpty() ) + return null; + Query query; + query = termQuery(map); if(query!=null) return query; + query = booleanQuery(map); if(query!=null) return query; + return null; } - public TopDocs search(Query query,int n) { + private SortField sortField(LuanState luan,List<Object> list,String pos) throws LuanException { + int size = list.size(); + if( size < 2 || size > 3 ) + throw luan.exception("invalid sort field"+pos); + Object obj0 = list.get(0); + Object obj1 = list.get(1); + if( !(obj0 instanceof String && obj1 instanceof String) ) + throw luan.exception("invalid sort field"+pos); + String field = (String)obj0; + SortField.Type type; try { - return searcher.search(query,n); - } catch(IOException e) { - throw new RuntimeException(e); + type = SortField.Type.valueOf( ((String)obj1).toUpperCase() ); + } catch(IllegalArgumentException e) { + throw luan.exception("invalid sort field type"+pos); } + if( size == 2 ) + return new SortField(field,type); + Object obj2 = list.get(2); + if( !(obj2 instanceof Boolean) ) + throw luan.exception("invalid sort field"+pos+", 'reverse' must be boolean"); + boolean reverse = (Boolean)obj2; + return new SortField(field,type,reverse); } - public TopFieldDocs search(Query query,int n,Sort sort) { + private Sort sort(LuanState luan,LuanTable sortTbl) throws LuanException { + if( !sortTbl.isList() ) + throw luan.exception("invalid sort, must be list"); + List<Object> list = sortTbl.asList(); + if( list.isEmpty() ) + throw luan.exception("sort cannot be empty"); + if( list.get(0) instanceof String ) + return new Sort(sortField(luan,list,"")); + SortField[] flds = new SortField[list.size()]; + for( int i=0; i<flds.length; i++ ) { + Object obj = list.get(i); + if( !(obj instanceof LuanTable) ) + throw luan.exception("invalid sort parameter at position "+(i+1)); + LuanTable fldTbl = (LuanTable)obj; + if( !fldTbl.isList() ) + throw luan.exception("invalid sort field at position "+(i+1)+", must be list"); + flds[i] = sortField(luan,fldTbl.asList()," at position "+(i+1)); + } + return new Sort(flds); + } + + public Object[] search( LuanState luan, LuanTable queryTbl, int n, LuanTable sortTbl ) throws LuanException, IOException { + Query query = query(queryTbl); + if( query == null ) + throw luan.exception("invalid query"); + TopDocs td = sortTbl==null ? searcher.search(query,n) : searcher.search(query,n,sort(luan,sortTbl)); + final ScoreDoc[] scoreDocs = td.scoreDocs; + LuanFunction results = new LuanFunction() { + int i = 0; + + @Override public Object call(LuanState luan,Object[] args) throws LuanException { + if( i >= scoreDocs.length ) + return LuanFunction.NOTHING; + try { + LuanTable doc = doc(scoreDocs[i++].doc); + return doc; + } catch(IOException e) { + throw luan.exception(e); + } + } + }; + return new Object[]{ results, scoreDocs.length, td.totalHits }; + } + + private void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException { + t.put( method, new LuanJavaFunction(LuceneSearcher.class.getMethod(method,parameterTypes),this) ); + } + + LuanTable table() { + LuanTable tbl = Luan.newTable(); try { - return searcher.search(query,n,sort); - } catch(IOException e) { + add( tbl, "search", LuanState.class, LuanTable.class, Integer.TYPE, LuanTable.class ); + } catch(NoSuchMethodException e) { throw new RuntimeException(e); } + return tbl; } - public Iterable<LuanTable> docs(TopDocs td) { - final ScoreDoc[] scoreDocs = td.scoreDocs; - return new Iterable<LuanTable>() { - public Iterator<LuanTable> iterator() { - return new Iterator<LuanTable>() { - private int i = 0; - - public boolean hasNext() { - return i < scoreDocs.length; - } - - public LuanTable next() { - if( !hasNext() ) - throw new NoSuchElementException(); - return doc(scoreDocs[i++].doc); - } - - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - }; - } }