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();
-					}
-				};
-			}
-		};
-	}
 }