Mercurial Hosting > luan
changeset 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 | a35417bf493a |
children | ef39bc4d3f70 |
files | core/src/luan/LuanTable.java core/src/luan/LuanTableImpl.java lucene/src/luan/modules/lucene/Lucene.luan lucene/src/luan/modules/lucene/LuceneIndex.java lucene/src/luan/modules/lucene/LuceneSearcher.java |
diffstat | 5 files changed, 167 insertions(+), 67 deletions(-) [+] |
line wrap: on
line diff
--- a/core/src/luan/LuanTable.java Wed Oct 01 02:15:39 2014 +0000 +++ b/core/src/luan/LuanTable.java Wed Oct 01 06:55:14 2014 +0000 @@ -6,6 +6,7 @@ public interface LuanTable extends Iterable<Map.Entry<Object,Object>> { + public boolean isList(); public List<Object> asList(); public Map<Object,Object> asMap(); public Object get(Object key);
--- a/core/src/luan/LuanTableImpl.java Wed Oct 01 02:15:39 2014 +0000 +++ b/core/src/luan/LuanTableImpl.java Wed Oct 01 06:55:14 2014 +0000 @@ -79,7 +79,7 @@ clone.metatable = cloner.get(metatable); } - public boolean isList() { + @Override public boolean isList() { return map==null || map.isEmpty(); }
--- a/lucene/src/luan/modules/lucene/Lucene.luan Wed Oct 01 02:15:39 2014 +0000 +++ b/lucene/src/luan/modules/lucene/Lucene.luan Wed Oct 01 06:55:14 2014 +0000 @@ -2,12 +2,12 @@ import "luan.modules.lucene.LuceneIndex" standard_fields = { - "type" = "type index"; - "id" = "id index"; + type = "type index"; + id = "id index"; } function Index(indexDir) - local index LuceneIndex.new(indexDir).table() + local index = LuceneIndex.new(indexDir).table() function index.save_document(doc) index.Writer( function(writer) @@ -21,5 +21,17 @@ end ) end + function index.get_document(query) + index.Searcher( function(searcher) + local results, _, total_hits = searcher.search(query,1) + if total_hits == 0 then + return nil + elseif total_hits > 1 then + error "found " .. total_hits .. " documents" + end + return results() + end ) + end + return index end
--- a/lucene/src/luan/modules/lucene/LuceneIndex.java Wed Oct 01 02:15:39 2014 +0000 +++ b/lucene/src/luan/modules/lucene/LuceneIndex.java Wed Oct 01 06:55:14 2014 +0000 @@ -88,7 +88,7 @@ private long idLim = 0; private final int idBatch = 10; - private void initId() { + private void initId() throws IOException { TopDocs td = searcher.search(new TermQuery(new Term(FLD_TYPE,"next_id")),1); switch(td.totalHits) { case 0: @@ -119,27 +119,6 @@ } } - public LuanTable getDocument(String id) { - return getDocument(new Term(LuceneWriter.FLD_ID,id)); - } - - public LuanTable getDocument(Term term) { - LuceneSearcher searcher = openSearcher(); - try { - TopDocs td = searcher.search(new TermQuery(term),1); - switch(td.totalHits) { - case 0: - return null; - case 1: - return searcher.doc(td.scoreDocs[0].doc); - default: - throw new RuntimeException(); - } - } finally { - searcher.close(); - } - } - public void backup(String zipFile) { if( !zipFile.endsWith(".zip") ) @@ -180,6 +159,15 @@ } } + public void Searcher(LuanState luan,LuanFunction fn) throws LuanException, IOException { + LuceneSearcher searcher = openSearcher(); + try { + luan.call( fn, new Object[]{searcher.table()} ); + } finally { + searcher.close(); + } + } + private void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException { t.put( method, new LuanJavaFunction(LuceneIndex.class.getMethod(method,parameterTypes),this) ); } @@ -189,6 +177,8 @@ try { add( tbl, "to_string" ); add( tbl, "backup", String.class ); + add( tbl, "Writer", LuanState.class, LuanFunction.class ); + add( tbl, "Searcher", LuanState.class, LuanFunction.class ); } catch(NoSuchMethodException e) { throw new RuntimeException(e); }
--- 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(); - } - }; - } - }; - } }