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