Mercurial Hosting > luan
diff lucene/src/luan/modules/lucene/LuceneIndex.java @ 545:ddcd4296107a
clean up lucene search
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 14 Jun 2015 01:34:42 -0600 |
parents | c5a93767cc5c |
children | eaef1005ab87 |
line wrap: on
line diff
--- a/lucene/src/luan/modules/lucene/LuceneIndex.java Fri Jun 12 19:11:44 2015 -0600 +++ b/lucene/src/luan/modules/lucene/LuceneIndex.java Sun Jun 14 01:34:42 2015 -0600 @@ -18,6 +18,7 @@ import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.Term; import org.apache.lucene.index.SnapshotDeletionPolicy; +import org.apache.lucene.index.AtomicReaderContext; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.util.Version; @@ -27,6 +28,10 @@ import org.apache.lucene.search.Sort; import org.apache.lucene.search.SortField; import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.TotalHitCountCollector; +import org.apache.lucene.search.ScoreDoc; +import org.apache.lucene.search.Collector; +import org.apache.lucene.search.Scorer; import sane.lucene.queryparser.SaneQueryParser; import sane.lucene.queryparser.FieldParser; import sane.lucene.queryparser.MultiFieldParser; @@ -41,6 +46,7 @@ import luan.LuanJavaFunction; import luan.LuanException; import luan.LuanMeta; +import luan.LuanRuntimeException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,16 +58,19 @@ private static final Analyzer analyzer = new KeywordAnalyzer(); public static final FieldParser STRING_FIELD_PARSER = new StringFieldParser(analyzer); + final LuanTable myTable; final Lock writeLock = new ReentrantLock(); private final File indexDir; final SnapshotDeletionPolicy snapshotDeletionPolicy; final IndexWriter writer; private DirectoryReader reader; - private LuceneSearcher searcher; + private IndexSearcher searcher; + private final ThreadLocal<IndexSearcher> threadLocalSearcher = new ThreadLocal<IndexSearcher>(); private boolean isClosed = false; private final MultiFieldParser mfp = new MultiFieldParser(); - public LuceneIndex(LuanState luan,String indexDirStr) throws LuanException, IOException { + public LuceneIndex(LuanState luan,String indexDirStr,LuanTable myTable) throws LuanException, IOException { + this.myTable = myTable; mfp.fields.put( "type", STRING_FIELD_PARSER ); mfp.fields.put( "id", NumberFieldParser.LONG ); File indexDir = new File(indexDirStr); @@ -75,7 +84,7 @@ writer.commit(); // commit index creation reader = DirectoryReader.open(dir); luan.onClose(this); - searcher = new LuceneSearcher(this,reader); + searcher = new IndexSearcher(reader); initId(luan); } @@ -87,17 +96,22 @@ return new LuceneWriter(this); } - synchronized LuceneSearcher openSearcher() throws IOException { + private synchronized IndexSearcher openSearcher() throws IOException { DirectoryReader newReader = DirectoryReader.openIfChanged(reader); if( newReader != null ) { reader.decRef(); reader = newReader; - searcher = new LuceneSearcher(this,reader); + searcher = new IndexSearcher(reader); } reader.incRef(); return searcher; } + // call in finally block + private static void close(IndexSearcher searcher) throws IOException { + searcher.getIndexReader().decRef(); + } + LuceneSnapshot openSnapshot() throws IOException { return new LuceneSnapshot(this); } @@ -119,7 +133,6 @@ private final int idBatch = 10; private void initId(LuanState luan) throws LuanException, IOException { - IndexSearcher searcher = this.searcher.searcher; TopDocs td = searcher.search(new TermQuery(new Term("type","next_id")),1); switch(td.totalHits) { case 0: @@ -172,7 +185,7 @@ return writer.getDirectory().toString(); } - public void Writer(LuanState luan,LuanFunction fn) throws LuanException, IOException { + public void writer(LuanState luan,LuanFunction fn) throws LuanException, IOException { LuceneWriter writer = openWriter(); try { luan.call( fn, new Object[]{writer.table()} ); @@ -182,15 +195,6 @@ } } - public Object Searcher(LuanState luan,LuanFunction fn) throws LuanException, IOException { - LuceneSearcher searcher = openSearcher(); - try { - return luan.call( fn, new Object[]{searcher.table()} ); - } finally { - searcher.close(); - } - } - public void close() throws IOException { if( !isClosed ) { writer.close(); @@ -209,6 +213,100 @@ + private static class DocFn extends LuanFunction { + final IndexSearcher searcher; + int docID; + + DocFn(IndexSearcher searcher) { + this.searcher = searcher; + } + + @Override public Object call(LuanState luan,Object[] args) throws LuanException { + try { + return LuceneDocument.toTable(luan,searcher.doc(docID)); + } catch(IOException e) { + throw luan.exception(e); + } + } + } + + private static abstract class MyCollector extends Collector { + int docBase; + int i = 0; + + @Override public void setScorer(Scorer scorer) {} + @Override public void setNextReader(AtomicReaderContext context) { + this.docBase = context.docBase; + } + @Override public boolean acceptsDocsOutOfOrder() { + return true; + } + } + + public int advanced_search( final LuanState luan, String queryStr, LuanFunction fn, Integer n, String sortStr ) throws LuanException, IOException, ParseException { + Utils.checkNotNull(luan,queryStr); + Query query = parseQuery(queryStr); + IndexSearcher searcher = threadLocalSearcher.get(); + boolean inTransaction = searcher != null; + if( !inTransaction ) + searcher = openSearcher(); + try { + if( fn!=null && n==null ) { + if( sortStr != null ) + throw luan.exception("sort must be nil when n is nil"); + final DocFn docFn = new DocFn(searcher); + MyCollector col = new MyCollector() { + @Override public void collect(int doc) { + try { + docFn.docID = doc; + luan.call(fn,new Object[]{++i,docFn}); + } catch(LuanException e) { + throw new LuanRuntimeException(e); + } + } + }; + try { + searcher.search(query,col); + } catch(LuanRuntimeException e) { + throw (LuanException)e.getCause(); + } + return col.i; + } + if( fn==null || n==0 ) { + TotalHitCountCollector thcc = new TotalHitCountCollector(); + searcher.search(query,thcc); + return thcc.getTotalHits(); + } + Sort sort = sortStr==null ? null : parseSort(sortStr); + TopDocs td = sort==null ? searcher.search(query,n) : searcher.search(query,n,sort); + final ScoreDoc[] scoreDocs = td.scoreDocs; + DocFn docFn = new DocFn(searcher); + for( int i=0; i<scoreDocs.length; i++ ) { + docFn.docID = scoreDocs[i].doc; + luan.call(fn,new Object[]{i+1,docFn}); + } + return td.totalHits; + } finally { + if( !inTransaction ) + close(searcher); + } + } + + public Object search_in_transaction(LuanState luan,LuanFunction fn) throws LuanException, IOException { + if( threadLocalSearcher.get() != null ) + throw luan.exception("can't nest search_in_transaction calls"); + IndexSearcher searcher = openSearcher(); + threadLocalSearcher.set(searcher); + try { + return luan.call(fn); + } finally { + threadLocalSearcher.set(null); + close(searcher); + } + } + + + public final LuanMeta indexedFieldsMeta = new LuanMeta() { @Override public boolean canNewindex() {