comparison lucene/src/luan/modules/lucene/LuceneIndex.java @ 646:cdc70de628b5

simplify LuanException
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 29 Mar 2016 19:58:39 -0600
parents 8281a248c47e
children b21d82ee5756
comparison
equal deleted inserted replaced
645:859c0dedc8b6 646:cdc70de628b5
113 writer = new IndexWriter(dir,conf); 113 writer = new IndexWriter(dir,conf);
114 writer.commit(); // commit index creation 114 writer.commit(); // commit index creation
115 reader = DirectoryReader.open(dir); 115 reader = DirectoryReader.open(dir);
116 luan.onClose(this); 116 luan.onClose(this);
117 searcher = new IndexSearcher(reader); 117 searcher = new IndexSearcher(reader);
118 initId(luan); 118 initId();
119 } 119 }
120 120
121 121
122 122
123 public void delete_all() throws IOException { 123 public void delete_all() throws IOException {
153 153
154 public void save(LuanState luan,LuanTable doc) throws LuanException, IOException { 154 public void save(LuanState luan,LuanTable doc) throws LuanException, IOException {
155 Set indexedOnlySet = new HashSet(); 155 Set indexedOnlySet = new HashSet();
156 Object typeObj = doc.get(luan,"type"); 156 Object typeObj = doc.get(luan,"type");
157 if( typeObj==null ) 157 if( typeObj==null )
158 throw new LuanException(luan,"missing 'type' field"); 158 throw new LuanException("missing 'type' field");
159 if( !(typeObj instanceof String) ) 159 if( !(typeObj instanceof String) )
160 throw new LuanException(luan,"type must be string"); 160 throw new LuanException("type must be string");
161 String type = (String)typeObj; 161 String type = (String)typeObj;
162 Object indexedOnlyObj = indexed_only_fields.get(luan,type); 162 Object indexedOnlyObj = indexed_only_fields.get(luan,type);
163 if( indexedOnlyObj != null ) { 163 if( indexedOnlyObj != null ) {
164 if( !(indexedOnlyObj instanceof LuanTable) ) 164 if( !(indexedOnlyObj instanceof LuanTable) )
165 throw new LuanException(luan,"indexed_only_fields elements must be tables"); 165 throw new LuanException("indexed_only_fields elements must be tables");
166 LuanTable indexedOnly = (LuanTable)indexedOnlyObj; 166 LuanTable indexedOnly = (LuanTable)indexedOnlyObj;
167 for( Map.Entry<Object,Object> entry : indexedOnly.iterable(luan) ) { 167 for( Map.Entry<Object,Object> entry : indexedOnly.iterable(luan) ) {
168 Object key = entry.getKey(); 168 Object key = entry.getKey();
169 if( !(key instanceof String) ) 169 if( !(key instanceof String) )
170 throw new LuanException(luan,"indexed_only_fields."+type+" entries must be strings"); 170 throw new LuanException("indexed_only_fields."+type+" entries must be strings");
171 String name = (String)key; 171 String name = (String)key;
172 Object value = entry.getValue(); 172 Object value = entry.getValue();
173 if( !(value instanceof LuanFunction) ) 173 if( !(value instanceof LuanFunction) )
174 throw new LuanException(luan,"indexed_only_fields."+type+" values must be functions"); 174 throw new LuanException("indexed_only_fields."+type+" values must be functions");
175 LuanFunction fn = (LuanFunction)value; 175 LuanFunction fn = (LuanFunction)value;
176 value = Luan.first(fn.call(luan,new Object[]{doc})); 176 value = Luan.first(fn.call(luan,new Object[]{doc}));
177 doc.put(luan, name, value ); 177 doc.put(luan, name, value );
178 indexedOnlySet.add(name); 178 indexedOnlySet.add(name);
179 } 179 }
181 Object obj = doc.get(luan,"id"); 181 Object obj = doc.get(luan,"id");
182 Long id; 182 Long id;
183 try { 183 try {
184 id = (Long)obj; 184 id = (Long)obj;
185 } catch(ClassCastException e) { 185 } catch(ClassCastException e) {
186 throw new LuanException(luan,"id should be Long but is "+obj.getClass().getSimpleName()); 186 throw new LuanException("id should be Long but is "+obj.getClass().getSimpleName());
187 } 187 }
188 188
189 boolean commit = !writeLock.isHeldByCurrentThread(); 189 boolean commit = !writeLock.isHeldByCurrentThread();
190 writeLock.lock(); 190 writeLock.lock();
191 try { 191 try {
216 216
217 private long id = 0; 217 private long id = 0;
218 private long idLim = 0; 218 private long idLim = 0;
219 private final int idBatch = 10; 219 private final int idBatch = 10;
220 220
221 private void initId(LuanState luan) throws LuanException, IOException { 221 private void initId() throws LuanException, IOException {
222 TopDocs td = searcher.search(new TermQuery(new Term("type","next_id")),1); 222 TopDocs td = searcher.search(new TermQuery(new Term("type","next_id")),1);
223 /* 223 /*
224 // tmp hack 224 // tmp hack
225 if( td.totalHits == 0 ) { 225 if( td.totalHits == 0 ) {
226 td = searcher.search(new TermQuery(new Term("type index","next_id")),1); 226 td = searcher.search(new TermQuery(new Term("type index","next_id")),1);
256 } 256 }
257 return id; 257 return id;
258 } 258 }
259 259
260 260
261 public void backup(LuanState luan,String zipFile) throws LuanException, IOException { 261 public void backup(String zipFile) throws LuanException, IOException {
262 if( !zipFile.endsWith(".zip") ) 262 if( !zipFile.endsWith(".zip") )
263 throw new LuanException(luan,"file "+zipFile+" doesn't end with '.zip'"); 263 throw new LuanException("file "+zipFile+" doesn't end with '.zip'");
264 IndexCommit ic = snapshotDeletionPolicy.snapshot(); 264 IndexCommit ic = snapshotDeletionPolicy.snapshot();
265 try { 265 try {
266 ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile)); 266 ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile));
267 for( String fileName : ic.getFileNames() ) { 267 for( String fileName : ic.getFileNames() ) {
268 out.putNextEntry(new ZipEntry(fileName)); 268 out.putNextEntry(new ZipEntry(fileName));
309 this.searcher = searcher; 309 this.searcher = searcher;
310 } 310 }
311 311
312 @Override public Object call(LuanState luan,Object[] args) throws LuanException { 312 @Override public Object call(LuanState luan,Object[] args) throws LuanException {
313 try { 313 try {
314 return toTable(luan,searcher.doc(docID)); 314 return toTable(searcher.doc(docID));
315 } catch(IOException e) { 315 } catch(IOException e) {
316 throw new LuanException(luan,e); 316 throw new LuanException(e);
317 } 317 }
318 } 318 }
319 } 319 }
320 320
321 private static abstract class MyCollector extends Collector { 321 private static abstract class MyCollector extends Collector {
350 public void ensure_open() throws IOException { 350 public void ensure_open() throws IOException {
351 close(openSearcher()); 351 close(openSearcher());
352 } 352 }
353 353
354 public int advanced_search( final LuanState luan, String queryStr, LuanFunction fn, Integer n, String sortStr ) throws LuanException, IOException, ParseException { 354 public int advanced_search( final LuanState luan, String queryStr, LuanFunction fn, Integer n, String sortStr ) throws LuanException, IOException, ParseException {
355 Utils.checkNotNull(luan,queryStr); 355 Utils.checkNotNull(queryStr);
356 Query query = SaneQueryParser.parseQuery(mfp,queryStr); 356 Query query = SaneQueryParser.parseQuery(mfp,queryStr);
357 IndexSearcher searcher = threadLocalSearcher.get(); 357 IndexSearcher searcher = threadLocalSearcher.get();
358 boolean inTransaction = searcher != null; 358 boolean inTransaction = searcher != null;
359 if( !inTransaction ) 359 if( !inTransaction )
360 searcher = openSearcher(); 360 searcher = openSearcher();
361 try { 361 try {
362 if( fn!=null && n==null ) { 362 if( fn!=null && n==null ) {
363 if( sortStr != null ) 363 if( sortStr != null )
364 throw new LuanException(luan,"sort must be nil when n is nil"); 364 throw new LuanException("sort must be nil when n is nil");
365 final DocFn docFn = new DocFn(searcher); 365 final DocFn docFn = new DocFn(searcher);
366 MyCollector col = new MyCollector() { 366 MyCollector col = new MyCollector() {
367 @Override public void collect(int doc) { 367 @Override public void collect(int doc) {
368 try { 368 try {
369 docFn.docID = docBase + doc; 369 docFn.docID = docBase + doc;
400 } 400 }
401 } 401 }
402 402
403 public Object search_in_transaction(LuanState luan,LuanFunction fn) throws LuanException, IOException { 403 public Object search_in_transaction(LuanState luan,LuanFunction fn) throws LuanException, IOException {
404 if( threadLocalSearcher.get() != null ) 404 if( threadLocalSearcher.get() != null )
405 throw new LuanException(luan,"can't nest search_in_transaction calls"); 405 throw new LuanException("can't nest search_in_transaction calls");
406 IndexSearcher searcher = openSearcher(); 406 IndexSearcher searcher = openSearcher();
407 threadLocalSearcher.set(searcher); 407 threadLocalSearcher.set(searcher);
408 try { 408 try {
409 return fn.call(luan); 409 return fn.call(luan);
410 } finally { 410 } finally {
425 return mfp.fields.get(key); 425 return mfp.fields.get(key);
426 } 426 }
427 427
428 @Override public void __new_index(LuanState luan,LuanTable tbl,Object key,Object value) throws LuanException { 428 @Override public void __new_index(LuanState luan,LuanTable tbl,Object key,Object value) throws LuanException {
429 if( !(key instanceof String) ) 429 if( !(key instanceof String) )
430 throw new LuanException(luan,"key must be string"); 430 throw new LuanException("key must be string");
431 String field = (String)key; 431 String field = (String)key;
432 if( value==null ) { // delete 432 if( value==null ) { // delete
433 mfp.fields.remove(field); 433 mfp.fields.remove(field);
434 return; 434 return;
435 } 435 }
436 if( !(value instanceof FieldParser) ) 436 if( !(value instanceof FieldParser) )
437 throw new LuanException(luan,"value must be FieldParser like the values of Lucene.type"); 437 throw new LuanException("value must be FieldParser like the values of Lucene.type");
438 FieldParser parser = (FieldParser)value; 438 FieldParser parser = (FieldParser)value;
439 mfp.fields.put( field, parser ); 439 mfp.fields.put( field, parser );
440 } 440 }
441 441
442 @Override public final Iterator keys(LuanTable tbl) { 442 @Override public final Iterator keys(LuanTable tbl) {
449 449
450 }; 450 };
451 451
452 452
453 453
454 private IndexableField newField(LuanState luan,String name,Object value,Field.Store store,Set<String> indexed) 454 private IndexableField newField(String name,Object value,Field.Store store,Set<String> indexed)
455 throws LuanException 455 throws LuanException
456 { 456 {
457 if( value instanceof String ) { 457 if( value instanceof String ) {
458 String s = (String)value; 458 String s = (String)value;
459 FieldParser fp = mfp.fields.get(name); 459 FieldParser fp = mfp.fields.get(name);
489 } 489 }
490 } else if( value instanceof byte[] ) { 490 } else if( value instanceof byte[] ) {
491 byte[] b = (byte[])value; 491 byte[] b = (byte[])value;
492 return new StoredField(name, b); 492 return new StoredField(name, b);
493 } else 493 } else
494 throw new LuanException(luan,"invalid value type "+value.getClass()+"' for '"+name+"'"); 494 throw new LuanException("invalid value type "+value.getClass()+"' for '"+name+"'");
495 } 495 }
496 496
497 private Document toLucene(LuanState luan,LuanTable table,Set indexOnly) throws LuanException { 497 private Document toLucene(LuanState luan,LuanTable table,Set indexOnly) throws LuanException {
498 Set<String> indexed = mfp.fields.keySet(); 498 Set<String> indexed = mfp.fields.keySet();
499 Document doc = new Document(); 499 Document doc = new Document();
500 for( Map.Entry<Object,Object> entry : table.iterable(luan) ) { 500 for( Map.Entry<Object,Object> entry : table.iterable(luan) ) {
501 Object key = entry.getKey(); 501 Object key = entry.getKey();
502 if( !(key instanceof String) ) 502 if( !(key instanceof String) )
503 throw new LuanException(luan,"key must be string"); 503 throw new LuanException("key must be string");
504 String name = (String)key; 504 String name = (String)key;
505 Object value = entry.getValue(); 505 Object value = entry.getValue();
506 Field.Store store = indexOnly.contains(name) ? Field.Store.NO : Field.Store.YES; 506 Field.Store store = indexOnly.contains(name) ? Field.Store.NO : Field.Store.YES;
507 if( !(value instanceof LuanTable) ) { 507 if( !(value instanceof LuanTable) ) {
508 doc.add(newField(luan, name, value, store, indexed)); 508 doc.add(newField(name, value, store, indexed));
509 } else { // list 509 } else { // list
510 LuanTable list = (LuanTable)value; 510 LuanTable list = (LuanTable)value;
511 for( Object el : list.asList() ) { 511 for( Object el : list.asList() ) {
512 doc.add(newField(luan, name, el, store, indexed)); 512 doc.add(newField(name, el, store, indexed));
513 } 513 }
514 } 514 }
515 } 515 }
516 return doc; 516 return doc;
517 } 517 }
518 518
519 private static Object getValue(LuanState luan,IndexableField ifld) throws LuanException { 519 private static Object getValue(IndexableField ifld) throws LuanException {
520 BytesRef br = ifld.binaryValue(); 520 BytesRef br = ifld.binaryValue();
521 if( br != null ) 521 if( br != null )
522 return br.bytes; 522 return br.bytes;
523 Number n = ifld.numericValue(); 523 Number n = ifld.numericValue();
524 if( n != null ) 524 if( n != null )
525 return n; 525 return n;
526 String s = ifld.stringValue(); 526 String s = ifld.stringValue();
527 if( s != null ) 527 if( s != null )
528 return s; 528 return s;
529 throw new LuanException(luan,"invalid field type for "+ifld); 529 throw new LuanException("invalid field type for "+ifld);
530 } 530 }
531 531
532 private static LuanTable toTable(LuanState luan,Document doc) throws LuanException { 532 private static LuanTable toTable(Document doc) throws LuanException {
533 if( doc==null ) 533 if( doc==null )
534 return null; 534 return null;
535 LuanTable table = new LuanTable(); 535 LuanTable table = new LuanTable();
536 for( IndexableField ifld : doc ) { 536 for( IndexableField ifld : doc ) {
537 String name = ifld.name(); 537 String name = ifld.name();
538 Object value = getValue(luan,ifld); 538 Object value = getValue(ifld);
539 Object old = table.rawGet(name); 539 Object old = table.rawGet(name);
540 if( old == null ) { 540 if( old == null ) {
541 table.rawPut(name,value); 541 table.rawPut(name,value);
542 } else { 542 } else {
543 LuanTable list; 543 LuanTable list;