1460
|
1 package goodjava.lucene.api;
|
|
2
|
|
3 import java.io.IOException;
|
|
4 import java.util.Map;
|
|
5 import java.util.HashMap;
|
|
6 import java.util.List;
|
|
7 import org.apache.lucene.analysis.Analyzer;
|
|
8 import org.apache.lucene.document.Document;
|
|
9 import org.apache.lucene.document.Field;
|
|
10 import org.apache.lucene.document.StoredField;
|
|
11 import org.apache.lucene.document.StringField;
|
|
12 import org.apache.lucene.document.TextField;
|
|
13 import org.apache.lucene.document.IntField;
|
|
14 import org.apache.lucene.document.LongField;
|
|
15 import org.apache.lucene.document.DoubleField;
|
|
16 import org.apache.lucene.document.FloatField;
|
|
17 import org.apache.lucene.index.IndexWriter;
|
|
18 import org.apache.lucene.index.IndexWriterConfig;
|
|
19 import org.apache.lucene.index.Term;
|
|
20 import org.apache.lucene.index.DirectoryReader;
|
|
21 import org.apache.lucene.index.IndexReader;
|
|
22 import org.apache.lucene.search.Query;
|
|
23 import org.apache.lucene.search.IndexSearcher;
|
|
24 import org.apache.lucene.store.Directory;
|
|
25 import org.apache.lucene.util.Version;
|
|
26
|
|
27
|
|
28 public final class LuceneIndexWriter implements GoodIndexWriter {
|
1465
|
29 private final FieldAnalyzer fieldAnalyzer = new FieldAnalyzer();
|
|
30 public final Version luceneVersion;
|
1460
|
31 public final IndexWriterConfig luceneConfig;
|
1465
|
32 public final IndexWriter luceneWriter;
|
1460
|
33 public final GoodIndexWriterConfig goodConfig;
|
|
34 private final Map<String,Boolean> indexedMap = new HashMap<String,Boolean>();
|
|
35
|
1465
|
36 public LuceneIndexWriter(Version luceneVersion,Directory dir,GoodIndexWriterConfig goodConfig) throws IOException {
|
|
37 this.luceneVersion = luceneVersion;
|
|
38 this.luceneConfig = new IndexWriterConfig(luceneVersion,fieldAnalyzer);
|
|
39 this.luceneWriter = new IndexWriter(dir,luceneConfig);
|
1460
|
40 this.goodConfig = goodConfig;
|
1465
|
41 luceneWriter.commit(); // commit index creation
|
1460
|
42 }
|
|
43
|
|
44 public void close() throws IOException {
|
|
45 luceneWriter.close();
|
|
46 }
|
|
47
|
|
48 public void commit() throws IOException {
|
|
49 luceneWriter.commit();
|
|
50 }
|
|
51
|
|
52 public void rollback() throws IOException {
|
|
53 luceneWriter.rollback();
|
|
54 }
|
|
55
|
|
56 public void deleteAll() throws IOException {
|
|
57 luceneWriter.deleteAll();
|
|
58 }
|
|
59
|
|
60 public void deleteDocuments(Query query) throws IOException {
|
|
61 luceneWriter.deleteDocuments(query);
|
|
62 }
|
|
63
|
|
64 public void addDocument(Map<String,Object> storedFields) throws IOException {
|
|
65 Document doc = newDocument(storedFields);
|
|
66 luceneWriter.addDocument(doc);
|
|
67 }
|
|
68
|
|
69 public void updateDocument(String keyFieldName,Map<String,Object> storedFields) throws IOException {
|
|
70 if( !isIndexed(keyFieldName) )
|
|
71 throw new RuntimeException("can't update using unindexed field "+keyFieldName);
|
|
72 if( fieldAnalyzer.isAdded(keyFieldName) )
|
|
73 throw new RuntimeException("can't update using analyzeed field "+keyFieldName);
|
|
74 Document doc = newDocument(storedFields);
|
|
75 Object keyValue = storedFields.get(keyFieldName);
|
|
76 if( keyValue==null )
|
|
77 throw new RuntimeException("no value for field "+keyFieldName);
|
|
78 Term term = LuceneUtils.term(keyFieldName,keyValue);
|
|
79 luceneWriter.updateDocument(term,doc);
|
|
80 }
|
|
81
|
|
82 private Document newDocument(Map<String,Object> storedFields) {
|
|
83 Document doc = new Document();
|
|
84 addFields(doc,storedFields,Field.Store.YES);
|
|
85 Map<String,Object> unstoredFields = goodConfig.getUnstoredFields(storedFields);
|
|
86 addFields(doc,unstoredFields,Field.Store.NO);
|
|
87 return doc;
|
|
88 }
|
|
89
|
|
90 private void addFields( Document doc, Map<String,Object> fields, Field.Store store ) {
|
|
91 for( Map.Entry<String,Object> entry : fields.entrySet() ) {
|
|
92 String name = entry.getKey();
|
|
93 Object value = entry.getValue();
|
|
94 if( value instanceof List ) {
|
|
95 for( Object v : (List)value ) {
|
|
96 doc.add( newField(name,v,store) );
|
|
97 }
|
|
98 } else {
|
|
99 doc.add( newField(name,value,store) );
|
|
100 }
|
|
101 }
|
|
102 }
|
|
103
|
|
104 private Field newField( String name, Object value, Field.Store store ) {
|
|
105 boolean isIndexed = isIndexed(name);
|
|
106 if( store==Field.Store.NO && !isIndexed )
|
|
107 throw new RuntimeException("field '"+name+"' is unstored and unindexed");
|
|
108 if( value instanceof String ) {
|
|
109 String s = (String)value;
|
|
110 if( !isIndexed ) {
|
|
111 return new StoredField(name,s);
|
|
112 } else if( !fieldAnalyzer.isAdded(name) ) {
|
|
113 return new StringField(name,s,store);
|
|
114 } else {
|
|
115 return new TextField(name,s,store);
|
|
116 }
|
|
117 } else if( value instanceof Integer ) {
|
|
118 int i = (Integer)value;
|
|
119 if( !isIndexed ) {
|
|
120 return new StoredField(name,i);
|
|
121 } else {
|
|
122 return new IntField(name,i,store);
|
|
123 }
|
|
124 } else if( value instanceof Long ) {
|
|
125 long i = (Long)value;
|
|
126 if( !isIndexed ) {
|
|
127 return new StoredField(name,i);
|
|
128 } else {
|
|
129 return new LongField(name,i,store);
|
|
130 }
|
|
131 } else if( value instanceof Double ) {
|
|
132 double i = (Double)value;
|
|
133 if( !isIndexed ) {
|
|
134 return new StoredField(name,i);
|
|
135 } else {
|
|
136 return new DoubleField(name,i,store);
|
|
137 }
|
|
138 } else if( value instanceof Float ) {
|
|
139 float i = (Float)value;
|
|
140 if( !isIndexed ) {
|
|
141 return new StoredField(name,i);
|
|
142 } else {
|
|
143 return new FloatField(name,i,store);
|
|
144 }
|
|
145 } else if( value instanceof byte[] ) {
|
|
146 if( isIndexed )
|
|
147 throw new RuntimeException("can't index byte field "+name);
|
|
148 byte[] b = (byte[])value;
|
|
149 return new StoredField(name, b);
|
|
150 } else
|
|
151 throw new RuntimeException("invalid value type "+value.getClass()+"' for field '"+name+"'");
|
|
152 }
|
|
153
|
|
154 private synchronized boolean isIndexed(String fieldName) {
|
|
155 Boolean b = indexedMap.get(fieldName);
|
|
156 if( b==null ) {
|
|
157 b = goodConfig.isIndexed(fieldName);
|
|
158 indexedMap.put(fieldName,b);
|
|
159 Analyzer analyzer = goodConfig.getAnalyzer(fieldName);
|
|
160 if( analyzer!=null )
|
|
161 fieldAnalyzer.add(fieldName,analyzer);
|
|
162 }
|
|
163 return b;
|
|
164 }
|
|
165
|
|
166
|
|
167 public void reindexDocuments(final String keyFieldName,Query query) throws IOException {
|
1465
|
168 IndexReader reader = openReader();
|
1460
|
169 final IndexSearcher searcher = new IndexSearcher(reader);
|
|
170 searcher.search( query, new GoodCollector(){
|
|
171 public void collectDoc(int iDoc) throws IOException {
|
|
172 Document doc = searcher.doc(iDoc);
|
|
173 Map<String,Object> storedFields = LuceneUtils.toMap(doc);
|
|
174 updateDocument(keyFieldName,storedFields);
|
|
175 }
|
|
176 });
|
|
177 reader.close();
|
|
178 }
|
1465
|
179
|
|
180 public IndexReader openReader() throws IOException {
|
|
181 return DirectoryReader.open(luceneWriter.getDirectory());
|
|
182 }
|
1460
|
183 }
|