diff --git a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java index 62c8ee8030..bd55ced160 100644 --- a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java +++ b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java @@ -417,7 +417,7 @@ private long getSeq(final IndexWriter writer, final String key, final long defau return Long.parseLong(entry.getValue()); } } - return 0L; + return defaultValue; } private void close(final String name, final IndexHolder holder) throws IOException { diff --git a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/lucene/LuceneIndex.java b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/lucene/LuceneIndex.java index 1384e75e75..cabf2b225f 100644 --- a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/lucene/LuceneIndex.java +++ b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/lucene/LuceneIndex.java @@ -31,6 +31,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.couchdb.nouveau.api.DocumentDeleteRequest; @@ -107,6 +108,7 @@ public class LuceneIndex extends Index { private final Analyzer analyzer; private final IndexWriter writer; private final SearcherManager searcherManager; + private final AtomicBoolean searcherManagerStale = new AtomicBoolean(false); private final LuceneIndexSchema schema; public LuceneIndex( @@ -147,12 +149,13 @@ public void doUpdate(final String docId, final DocumentUpdateRequest request) th final Document doc = toDocument(docId, request); schema.update(request.fields()); writer.updateDocument(docIdTerm, doc); + searcherManagerStale.set(true); } @Override public void doDelete(final String docId, final DocumentDeleteRequest request) throws IOException { - final Query query = docIdQuery(docId); - writer.deleteDocuments(query); + writer.deleteDocuments(docIdTerm(docId)); + searcherManagerStale.set(true); } @Override @@ -209,7 +212,9 @@ public SearchResults doSearch(final SearchRequest request) throws IOException { cm = new MultiCollectorManager(hits); } - searcherManager.maybeRefreshBlocking(); + if (searcherManagerStale.getAndSet(false)) { + searcherManager.maybeRefreshBlocking(); + } final IndexSearcher searcher = searcherManager.acquire(); try { @@ -514,10 +519,6 @@ private static byte[] toBytes(final BytesRef bytesRef) { return Arrays.copyOfRange(bytesRef.bytes, bytesRef.offset, bytesRef.offset + bytesRef.length); } - private static Query docIdQuery(final String docId) { - return new TermQuery(docIdTerm(docId)); - } - private static Term docIdTerm(final String docId) { return new Term("_id", docId); } diff --git a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/lucene/LuceneIndexSchema.java b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/lucene/LuceneIndexSchema.java index bf43512927..b453591ed4 100644 --- a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/lucene/LuceneIndexSchema.java +++ b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/lucene/LuceneIndexSchema.java @@ -56,6 +56,8 @@ private static Type fromField(final Field field) { private final ConcurrentMap map; + private final ConcurrentMap> pointsConfigCache = new ConcurrentHashMap<>(); + private LuceneIndexSchema(Map map) { this.map = new ConcurrentHashMap<>(map); this.map.put("_id", Type.STRING); @@ -78,7 +80,11 @@ public static LuceneIndexSchema fromString(final String schemaStr) { public void update(final Collection fields) { Objects.requireNonNull(fields); for (var field : fields) { - map.putIfAbsent(field.name(), Type.fromField(field)); + var type = Type.fromField(field); + var result = map.putIfAbsent(field.name(), type); + if (result == null && type == Type.DOUBLE) { + pointsConfigCache.clear(); + } assertType(field); } } @@ -102,6 +108,10 @@ public void assertType(final Field field) { } public Map toPointsConfigMap(final Locale locale) { + return pointsConfigCache.computeIfAbsent(locale, l -> buildPointsConfigMap(l)); + } + + private Map buildPointsConfigMap(final Locale locale) { Objects.requireNonNull(locale); var numberFormat = NumberFormat.getInstance(locale); var doublePointsConfig = new PointsConfig(numberFormat, Double.class); diff --git a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/resources/AnalyzeResource.java b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/resources/AnalyzeResource.java index 8da17b1c5c..14e65b3458 100644 --- a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/resources/AnalyzeResource.java +++ b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/resources/AnalyzeResource.java @@ -45,9 +45,8 @@ public final class AnalyzeResource { @POST public AnalyzeResponse analyzeText(@NotNull @Valid AnalyzeRequest request) throws IOException { - try { - final List tokens = tokenize(LuceneAnalyzerFactory.newAnalyzer(request.analyzer()), request.text()); - return new AnalyzeResponse(tokens); + try (Analyzer analyzer = LuceneAnalyzerFactory.newAnalyzer(request.analyzer())) { + return new AnalyzeResponse(tokenize(analyzer, request.text())); } catch (IllegalArgumentException e) { throw new WebApplicationException(request.analyzer() + " not a valid analyzer", Status.BAD_REQUEST); }