comparison src/luan/modules/lucene/LuceneIndex.java @ 1343:7d9a1f8894b0

lucene change indexed_only_field() to indexed_only_fields()
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 22 Feb 2019 10:12:05 -0700
parents 60599adc27b8
children dc2af9d5463b
comparison
equal deleted inserted replaced
1342:60599adc27b8 1343:7d9a1f8894b0
70 import luan.lib.parser.ParseException; 70 import luan.lib.parser.ParseException;
71 import luan.modules.Utils; 71 import luan.modules.Utils;
72 import luan.Luan; 72 import luan.Luan;
73 import luan.LuanTable; 73 import luan.LuanTable;
74 import luan.LuanFunction; 74 import luan.LuanFunction;
75 import luan.LuanCloner;
76 import luan.LuanException; 75 import luan.LuanException;
77 import luan.LuanRuntimeException; 76 import luan.LuanRuntimeException;
78 import luan.lib.logging.Logger; 77 import luan.lib.logging.Logger;
79 import luan.lib.logging.LoggerFactory; 78 import luan.lib.logging.LoggerFactory;
80 79
100 99
101 private static ConcurrentMap<File,AtomicInteger> globalWriteCounters = new ConcurrentHashMap<File,AtomicInteger>(); 100 private static ConcurrentMap<File,AtomicInteger> globalWriteCounters = new ConcurrentHashMap<File,AtomicInteger>();
102 private File fileDir; 101 private File fileDir;
103 private int writeCount; 102 private int writeCount;
104 103
105 private final ConcurrentMap<String,Map<String,LuanFunction>> indexedOnlyFields = new ConcurrentHashMap<String,Map<String,LuanFunction>>(); 104 private Set<String> indexOnly = new HashSet<String>();
106 private final Luan luanMine = new Luan();
107 private final LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
108 105
109 public LuceneIndex(Luan luan,String indexDirStr,FieldParser defaultFieldParser,String[] defaultFields) 106 public LuceneIndex(Luan luan,String indexDirStr,FieldParser defaultFieldParser,String[] defaultFields)
110 throws LuanException, IOException 107 throws LuanException, IOException
111 { 108 {
112 mfp = defaultFieldParser==null ? new MultiFieldParser() : new MultiFieldParser(defaultFieldParser,defaultFields); 109 mfp = defaultFieldParser==null ? new MultiFieldParser() : new MultiFieldParser(defaultFieldParser,defaultFields);
181 wrote(); 178 wrote();
182 writeLock.unlock(); 179 writeLock.unlock();
183 } 180 }
184 } 181 }
185 182
186 public void indexed_only_field(String type,String field,LuanFunction fn) { 183 public void indexed_only_fields(List<String> fields) {
187 fn = (LuanFunction)cloner.get(fn); 184 indexOnly.addAll(fields);
188 indexedOnlyFields.putIfAbsent(type,new ConcurrentHashMap<String,LuanFunction>());
189 Map<String,LuanFunction> map = indexedOnlyFields.get(type);
190 map.put(field,fn);
191 } 185 }
192 186
193 public void save(Luan luan,LuanTable doc,LuanTable boosts) 187 public void save(Luan luan,LuanTable doc,LuanTable boosts)
194 throws LuanException, IOException 188 throws LuanException, IOException
195 { 189 {
196 Set indexedOnlySet = new HashSet();
197 Object typeObj = doc.get("type");
198 if( typeObj==null )
199 throw new LuanException("missing 'type' field");
200 if( !(typeObj instanceof String) )
201 throw new LuanException("type must be string");
202 String type = (String)typeObj;
203 Map<String,LuanFunction> map = indexedOnlyFields.get(type);
204 if( map != null ) {
205 for( Map.Entry<String,LuanFunction> entry : map.entrySet() ) {
206 String name = entry.getKey();
207 LuanFunction fn = entry.getValue();
208 Object value = Luan.first(fn.call(doc));
209 doc.put( name, value );
210 indexedOnlySet.add(name);
211 }
212 }
213 Object obj = doc.get("id"); 190 Object obj = doc.get("id");
214 Long id; 191 Long id;
215 try { 192 try {
216 id = (Long)obj; 193 id = (Long)obj;
217 } catch(ClassCastException e) { 194 } catch(ClassCastException e) {
222 writeLock.lock(); 199 writeLock.lock();
223 try { 200 try {
224 if( id == null ) { 201 if( id == null ) {
225 id = nextId(luan); 202 id = nextId(luan);
226 doc.put("id",id); 203 doc.put("id",id);
227 writer.addDocument(toLucene(doc,indexedOnlySet,boosts)); 204 writer.addDocument(toLucene(doc,boosts));
228 } else { 205 } else {
229 writer.updateDocument( term("id",id), toLucene(doc,indexedOnlySet,boosts) ); 206 writer.updateDocument( term("id",id), toLucene(doc,boosts) );
230 } 207 }
231 if(commit) writer.commit(); 208 if(commit) writer.commit();
232 } finally { 209 } finally {
233 wrote(); 210 wrote();
234 writeLock.unlock(); 211 writeLock.unlock();
286 if( ++id > idLim ) { 263 if( ++id > idLim ) {
287 idLim += idBatch; 264 idLim += idBatch;
288 LuanTable doc = new LuanTable(luan); 265 LuanTable doc = new LuanTable(luan);
289 doc.rawPut( "type", "next_id" ); 266 doc.rawPut( "type", "next_id" );
290 doc.rawPut( FLD_NEXT_ID, idLim ); 267 doc.rawPut( FLD_NEXT_ID, idLim );
291 writer.updateDocument(new Term("type","next_id"),toLucene(doc,Collections.EMPTY_SET,null)); 268 writer.updateDocument(new Term("type","next_id"),toLucene(doc,null));
292 wrote(); 269 wrote();
293 } 270 }
294 return id; 271 return id;
295 } 272 }
296 273
493 } 470 }
494 mfp.fields.put( field, fp ); 471 mfp.fields.put( field, fp );
495 } 472 }
496 473
497 474
498 private IndexableField newField(String name,Object value,Field.Store store,Set<String> indexed,Float boost) 475 private IndexableField newField(String name,Object value,Set<String> indexed,Float boost)
499 throws LuanException 476 throws LuanException
500 { 477 {
501 IndexableField fld = newField2(name,value,store,indexed); 478 boolean hasBoost = boost!=null;
502 if( boost != null ) 479 IndexableField fld = newField2(name,value,indexed,hasBoost);
480 if( hasBoost )
503 ((Field)fld).setBoost(boost); 481 ((Field)fld).setBoost(boost);
504 return fld; 482 return fld;
505 } 483 }
506 484
507 private IndexableField newField2(String name,Object value,Field.Store store,Set<String> indexed) 485 private IndexableField newField2(String name,Object value,Set<String> indexed,boolean hasBoost)
508 throws LuanException 486 throws LuanException
509 { 487 {
488 Field.Store store = indexOnly.contains(name) ? Field.Store.NO : Field.Store.YES;
510 if( value instanceof String ) { 489 if( value instanceof String ) {
511 String s = (String)value; 490 String s = (String)value;
512 FieldParser fp = mfp.fields.get(name); 491 FieldParser fp = mfp.fields.get(name);
513 if( fp != null ) { 492 if( fp != null ) {
514 if( fp instanceof StringFieldParser && fp != STRING_FIELD_PARSER ) { 493 if( fp instanceof StringFieldParser && fp != STRING_FIELD_PARSER ) {
515 return new TextField(name, s, store); 494 return new TextField(name, s, store);
495 } else if (hasBoost) {
496 // fuck you modern lucene developers
497 return new Field(name, s, store, Field.Index.NOT_ANALYZED);
516 } else { 498 } else {
517 return new StringField(name, s, store); 499 return new StringField(name, s, store);
518 } 500 }
519 } else { 501 } else {
520 return new StoredField(name, s); 502 return new StoredField(name, s);
545 return new StoredField(name, b); 527 return new StoredField(name, b);
546 } else 528 } else
547 throw new LuanException("invalid value type "+value.getClass()+"' for '"+name+"'"); 529 throw new LuanException("invalid value type "+value.getClass()+"' for '"+name+"'");
548 } 530 }
549 531
550 private Document toLucene(LuanTable table,Set indexOnly,LuanTable boosts) throws LuanException { 532 private Document toLucene(LuanTable table,LuanTable boosts) throws LuanException {
551 Set<String> indexed = mfp.fields.keySet(); 533 Set<String> indexed = mfp.fields.keySet();
552 Document doc = new Document(); 534 Document doc = new Document();
553 for( Map.Entry<Object,Object> entry : table.iterable() ) { 535 for( Map.Entry<Object,Object> entry : table.iterable() ) {
554 Object key = entry.getKey(); 536 Object key = entry.getKey();
555 if( !(key instanceof String) ) 537 if( !(key instanceof String) )
556 throw new LuanException("key must be string"); 538 throw new LuanException("key must be string");
557 String name = (String)key; 539 String name = (String)key;
558 Object value = entry.getValue(); 540 Object value = entry.getValue();
559 Field.Store store = indexOnly.contains(name) ? Field.Store.NO : Field.Store.YES;
560 Float boost = null; 541 Float boost = null;
561 if( boosts != null ) { 542 if( boosts != null ) {
562 Object obj = boosts.get(name); 543 Object obj = boosts.get(name);
563 if( obj != null ) { 544 if( obj != null ) {
564 if( !(obj instanceof Number) ) 545 if( !(obj instanceof Number) )
565 throw new LuanException("boost '"+name+"' must be number"); 546 throw new LuanException("boost '"+name+"' must be number");
566 boost = ((Number)obj).floatValue(); 547 boost = ((Number)obj).floatValue();
567 } 548 }
568 } 549 }
569 if( !(value instanceof LuanTable) ) { 550 if( !(value instanceof LuanTable) ) {
570 doc.add(newField( name, value, store, indexed, boost )); 551 doc.add(newField( name, value, indexed, boost ));
571 } else { // list 552 } else { // list
572 LuanTable list = (LuanTable)value; 553 LuanTable list = (LuanTable)value;
573 for( Object el : list.asList() ) { 554 for( Object el : list.asList() ) {
574 doc.add(newField( name, el, store, indexed, boost )); 555 doc.add(newField( name, el, indexed, boost ));
575 } 556 }
576 } 557 }
577 } 558 }
578 return doc; 559 return doc;
579 } 560 }