From ef66d3ba8534972e054ed448c050f5296749e23e Mon Sep 17 00:00:00 2001 From: Robert Newson Date: Tue, 18 Aug 2026 14:56:07 +0100 Subject: [PATCH 1/5] use defaultValue in all cases --- .../main/java/org/apache/couchdb/nouveau/core/IndexManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 { From a6128de023b2c8e8cffa704687b7d4798bc0f290 Mon Sep 17 00:00:00 2001 From: Robert Newson Date: Tue, 18 Aug 2026 14:56:27 +0100 Subject: [PATCH 2/5] make delete method consistent with update method --- .../org/apache/couchdb/nouveau/lucene/LuceneIndex.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) 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..300c73ec01 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 @@ -151,8 +151,7 @@ public void doUpdate(final String docId, final DocumentUpdateRequest request) th @Override public void doDelete(final String docId, final DocumentDeleteRequest request) throws IOException { - final Query query = docIdQuery(docId); - writer.deleteDocuments(query); + writer.deleteDocuments(docIdTerm(docId)); } @Override @@ -514,10 +513,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); } From a253aa0589a0df73d2f3d499d2e663369b6f3133 Mon Sep 17 00:00:00 2001 From: Robert Newson Date: Tue, 18 Aug 2026 14:56:44 +0100 Subject: [PATCH 3/5] Analyzer's are Closeable, so ensure we close --- .../apache/couchdb/nouveau/resources/AnalyzeResource.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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); } From 272a447a64c00d13284d0f3c5225c6b9249cfee5 Mon Sep 17 00:00:00 2001 From: Robert Newson Date: Tue, 18 Aug 2026 20:30:29 +0100 Subject: [PATCH 4/5] refresh searchermanager only when index changes --- .../org/apache/couchdb/nouveau/lucene/LuceneIndex.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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 300c73ec01..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,11 +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 { writer.deleteDocuments(docIdTerm(docId)); + searcherManagerStale.set(true); } @Override @@ -208,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 { From addb17482ba7ea67575357f37a84f984ed4c4f13 Mon Sep 17 00:00:00 2001 From: Robert Newson Date: Tue, 18 Aug 2026 20:30:11 +0100 Subject: [PATCH 5/5] cache PointsConfig --- .../couchdb/nouveau/lucene/LuceneIndexSchema.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) 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);