Mercurial Hosting > luan
diff src/goodjava/lucene/api/LuceneIndexWriter.java @ 1460:3ab0d043370f
start lucene.api
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Mon, 23 Mar 2020 00:04:42 -0600 |
parents | |
children | 5e3870618377 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/goodjava/lucene/api/LuceneIndexWriter.java Mon Mar 23 00:04:42 2020 -0600 @@ -0,0 +1,176 @@ +package goodjava.lucene.api; + +import java.io.IOException; +import java.util.Map; +import java.util.HashMap; +import java.util.List; +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; +import org.apache.lucene.document.StoredField; +import org.apache.lucene.document.StringField; +import org.apache.lucene.document.TextField; +import org.apache.lucene.document.IntField; +import org.apache.lucene.document.LongField; +import org.apache.lucene.document.DoubleField; +import org.apache.lucene.document.FloatField; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.index.IndexWriterConfig; +import org.apache.lucene.index.Term; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.store.Directory; +import org.apache.lucene.util.Version; + + +public final class LuceneIndexWriter implements GoodIndexWriter { + final FieldAnalyzer fieldAnalyzer = new FieldAnalyzer(); + public final IndexWriterConfig luceneConfig; + public final GoodIndexWriterConfig goodConfig; + public final IndexWriter luceneWriter; + private final Map<String,Boolean> indexedMap = new HashMap<String,Boolean>(); + + public LuceneIndexWriter(Version matchVersion,Directory dir,GoodIndexWriterConfig goodConfig) throws IOException { + luceneConfig = new IndexWriterConfig(matchVersion,fieldAnalyzer); + luceneWriter = new IndexWriter(dir,luceneConfig); + this.goodConfig = goodConfig; + } + + public void close() throws IOException { + luceneWriter.close(); + } + + public void commit() throws IOException { + luceneWriter.commit(); + } + + public void rollback() throws IOException { + luceneWriter.rollback(); + } + + public void deleteAll() throws IOException { + luceneWriter.deleteAll(); + } + + public void deleteDocuments(Query query) throws IOException { + luceneWriter.deleteDocuments(query); + } + + public void addDocument(Map<String,Object> storedFields) throws IOException { + Document doc = newDocument(storedFields); + luceneWriter.addDocument(doc); + } + + public void updateDocument(String keyFieldName,Map<String,Object> storedFields) throws IOException { + if( !isIndexed(keyFieldName) ) + throw new RuntimeException("can't update using unindexed field "+keyFieldName); + if( fieldAnalyzer.isAdded(keyFieldName) ) + throw new RuntimeException("can't update using analyzeed field "+keyFieldName); + Document doc = newDocument(storedFields); + Object keyValue = storedFields.get(keyFieldName); + if( keyValue==null ) + throw new RuntimeException("no value for field "+keyFieldName); + Term term = LuceneUtils.term(keyFieldName,keyValue); + luceneWriter.updateDocument(term,doc); + } + + private Document newDocument(Map<String,Object> storedFields) { + Document doc = new Document(); + addFields(doc,storedFields,Field.Store.YES); + Map<String,Object> unstoredFields = goodConfig.getUnstoredFields(storedFields); + addFields(doc,unstoredFields,Field.Store.NO); + return doc; + } + + private void addFields( Document doc, Map<String,Object> fields, Field.Store store ) { + for( Map.Entry<String,Object> entry : fields.entrySet() ) { + String name = entry.getKey(); + Object value = entry.getValue(); + if( value instanceof List ) { + for( Object v : (List)value ) { + doc.add( newField(name,v,store) ); + } + } else { + doc.add( newField(name,value,store) ); + } + } + } + + private Field newField( String name, Object value, Field.Store store ) { + boolean isIndexed = isIndexed(name); + if( store==Field.Store.NO && !isIndexed ) + throw new RuntimeException("field '"+name+"' is unstored and unindexed"); + if( value instanceof String ) { + String s = (String)value; + if( !isIndexed ) { + return new StoredField(name,s); + } else if( !fieldAnalyzer.isAdded(name) ) { + return new StringField(name,s,store); + } else { + return new TextField(name,s,store); + } + } else if( value instanceof Integer ) { + int i = (Integer)value; + if( !isIndexed ) { + return new StoredField(name,i); + } else { + return new IntField(name,i,store); + } + } else if( value instanceof Long ) { + long i = (Long)value; + if( !isIndexed ) { + return new StoredField(name,i); + } else { + return new LongField(name,i,store); + } + } else if( value instanceof Double ) { + double i = (Double)value; + if( !isIndexed ) { + return new StoredField(name,i); + } else { + return new DoubleField(name,i,store); + } + } else if( value instanceof Float ) { + float i = (Float)value; + if( !isIndexed ) { + return new StoredField(name,i); + } else { + return new FloatField(name,i,store); + } + } else if( value instanceof byte[] ) { + if( isIndexed ) + throw new RuntimeException("can't index byte field "+name); + byte[] b = (byte[])value; + return new StoredField(name, b); + } else + throw new RuntimeException("invalid value type "+value.getClass()+"' for field '"+name+"'"); + } + + private synchronized boolean isIndexed(String fieldName) { + Boolean b = indexedMap.get(fieldName); + if( b==null ) { + b = goodConfig.isIndexed(fieldName); + indexedMap.put(fieldName,b); + Analyzer analyzer = goodConfig.getAnalyzer(fieldName); + if( analyzer!=null ) + fieldAnalyzer.add(fieldName,analyzer); + } + return b; + } + + + public void reindexDocuments(final String keyFieldName,Query query) throws IOException { + IndexReader reader = DirectoryReader.open(luceneWriter.getDirectory()); + final IndexSearcher searcher = new IndexSearcher(reader); + searcher.search( query, new GoodCollector(){ + public void collectDoc(int iDoc) throws IOException { + Document doc = searcher.doc(iDoc); + Map<String,Object> storedFields = LuceneUtils.toMap(doc); + updateDocument(keyFieldName,storedFields); + } + }); + reader.close(); + } +}