You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2026/03/22 18:01:31 UTC
(couchdb) 09/11: convert Search api classes to records
This is an automated email from the ASF dual-hosted git repository.
rnewson pushed a commit to branch nouveau-update-bundle
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit c4c16bd8fee2d9cfc9ac453926f5d80bad6ecb2f
Author: Robert Newson <rn...@apache.org>
AuthorDate: Sat Mar 21 20:27:47 2026 +0000
convert Search api classes to records
---
.../org/apache/couchdb/nouveau/api/SearchHit.java | 39 +---
.../apache/couchdb/nouveau/api/SearchRequest.java | 207 +++++++++------------
.../apache/couchdb/nouveau/api/SearchResults.java | 74 +-------
.../org/apache/couchdb/nouveau/core/Index.java | 2 +-
.../couchdb/nouveau/health/IndexHealthCheck.java | 12 +-
.../apache/couchdb/nouveau/lucene/LuceneIndex.java | 154 +++++++--------
.../couchdb/nouveau/api/SearchRequestTest.java | 15 +-
.../couchdb/nouveau/core/IndexManagerTest.java | 5 +-
.../couchdb/nouveau/lucene/LuceneIndexTest.java | 70 +++----
9 files changed, 225 insertions(+), 353 deletions(-)
diff --git a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/api/SearchHit.java b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/api/SearchHit.java
index 2e575fef1..9a0d8229b 100644
--- a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/api/SearchHit.java
+++ b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/api/SearchHit.java
@@ -18,43 +18,8 @@ import com.fasterxml.jackson.databind.annotation.JsonNaming;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.Collection;
-import java.util.Objects;
import org.apache.couchdb.nouveau.core.ser.PrimitiveWrapper;
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
-public class SearchHit {
-
- @NotEmpty
- private String id;
-
- @NotNull
- private PrimitiveWrapper<?>[] order;
-
- @NotNull
- private Collection<@NotNull StoredField> fields;
-
- public SearchHit() {}
-
- public SearchHit(final String id, final PrimitiveWrapper<?>[] order, final Collection<StoredField> fields) {
- this.id = id;
- this.order = Objects.requireNonNull(order);
- this.fields = Objects.requireNonNull(fields);
- }
-
- public String getId() {
- return id;
- }
-
- public PrimitiveWrapper<?>[] getOrder() {
- return order;
- }
-
- public Collection<StoredField> getFields() {
- return fields;
- }
-
- @Override
- public String toString() {
- return "SearchHit [id=" + id + ", order=" + order + ", fields=" + fields + "]";
- }
-}
+public record SearchHit(
+ @NotEmpty String id, @NotNull PrimitiveWrapper<?>[] order, @NotNull Collection<@NotNull StoredField> fields) {}
diff --git a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/api/SearchRequest.java b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/api/SearchRequest.java
index 8e4ebbf8d..948b080a7 100644
--- a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/api/SearchRequest.java
+++ b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/api/SearchRequest.java
@@ -13,7 +13,6 @@
package org.apache.couchdb.nouveau.api;
-import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import jakarta.validation.constraints.Max;
@@ -25,162 +24,126 @@ import jakarta.validation.constraints.PositiveOrZero;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Optional;
+import java.util.OptionalInt;
import org.apache.couchdb.nouveau.core.ser.PrimitiveWrapper;
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
-public class SearchRequest {
+public record SearchRequest(
+ @NotNull String query,
+ @PositiveOrZero long minUpdateSeq,
+ @PositiveOrZero long minPurgeSeq,
+ Optional<Locale> locale,
+ Optional<String> partition,
+ @Positive OptionalInt limit,
+ @NotNull Optional<List<@NotEmpty String>> sort,
+ @NotNull Optional<List<@NotEmpty String>> counts,
+ @NotNull Optional<Map<@NotEmpty String, List<@NotNull DoubleRange>>> ranges,
+ @NotNull Optional<PrimitiveWrapper<?>[]> after,
+ @Min(1) @Max(1000) OptionalInt topN) {
- @NotNull
- private String query;
-
- @PositiveOrZero
- private long minUpdateSeq;
-
- @PositiveOrZero
- private long minPurgeSeq;
-
- private Locale locale;
-
- private String partition;
-
- @Positive
- private int limit = 25;
-
- private List<@NotEmpty String> sort;
-
- private List<@NotEmpty String> counts;
-
- private Map<@NotEmpty String, List<@NotNull DoubleRange>> ranges;
-
- private PrimitiveWrapper<?>[] after;
-
- @Min(1)
- @Max(1000)
- private int topN = 10;
-
- public SearchRequest() {
- // Jackson deserialization
+ public int limitAsInt() {
+ return limit.orElse(25);
}
- public void setQuery(final String query) {
- this.query = query;
+ public int topNAsInt() {
+ return topN.orElse(10);
}
- @JsonProperty
- public String getQuery() {
- return query;
+ public boolean hasCounts() {
+ return !counts.isEmpty();
}
- public void setMinUpdateSeq(final long minUpdateSeq) {
- this.minUpdateSeq = minUpdateSeq;
+ public boolean hasRanges() {
+ return !ranges.isEmpty();
}
- @JsonProperty
- public long getMinUpdateSeq() {
- return minUpdateSeq;
+ public Locale getLocale() {
+ return locale.orElse(Locale.getDefault());
}
- public void setMinPurgeSeq(final long minPurgeSeq) {
- this.minPurgeSeq = minPurgeSeq;
- }
+ public static class Builder {
- @JsonProperty
- public long getMinPurgeSeq() {
- return minPurgeSeq;
- }
+ private String query;
- public void setLocale(final Locale locale) {
- this.locale = locale;
- }
+ private long minUpdateSeq;
- @JsonProperty
- public Locale getLocale() {
- return locale;
- }
+ private long minPurgeSeq;
- public void setPartition(final String partition) {
- this.partition = partition;
- }
+ private Optional<Locale> locale = Optional.empty();
- @JsonProperty
- public String getPartition() {
- return partition;
- }
+ private Optional<String> partition = Optional.empty();
- public boolean hasPartition() {
- return partition != null;
- }
+ private OptionalInt limit = OptionalInt.empty();
- public void setLimit(final int limit) {
- this.limit = limit;
- }
+ private Optional<List<String>> sort = Optional.empty();
- @JsonProperty
- public int getLimit() {
- return limit;
- }
+ private Optional<List<String>> counts = Optional.empty();
- public boolean hasSort() {
- return sort != null;
- }
+ private Optional<Map<String, List<DoubleRange>>> ranges = Optional.empty();
- @JsonProperty
- public List<String> getSort() {
- return sort;
- }
+ private Optional<PrimitiveWrapper<?>[]> after = Optional.empty();
- public void setSort(List<String> sort) {
- this.sort = sort;
- }
+ private OptionalInt topN = OptionalInt.empty();
- public boolean hasCounts() {
- return counts != null;
- }
+ public Builder setQuery(final String query) {
+ this.query = query;
+ return this;
+ }
- public void setCounts(final List<String> counts) {
- this.counts = counts;
- }
+ public Builder setMinUpdateSeq(final long minUpdateSeq) {
+ this.minUpdateSeq = minUpdateSeq;
+ return this;
+ }
- @JsonProperty
- public List<String> getCounts() {
- return counts;
- }
+ public Builder setMinPurgeSeq(final long minPurgeSeq) {
+ this.minPurgeSeq = minPurgeSeq;
+ return this;
+ }
- public boolean hasRanges() {
- return ranges != null;
- }
+ public Builder setLocale(final Locale locale) {
+ this.locale = Optional.of(locale);
+ return this;
+ }
- public void setRanges(final Map<String, List<DoubleRange>> ranges) {
- this.ranges = ranges;
- }
+ public Builder setPartition(final String partition) {
+ this.partition = Optional.of(partition);
+ return this;
+ }
- @JsonProperty
- public Map<String, List<DoubleRange>> getRanges() {
- return ranges;
- }
+ public Builder setLimit(final int limit) {
+ this.limit = OptionalInt.of(limit);
+ return this;
+ }
- public void setTopN(final int topN) {
- this.topN = topN;
- }
+ public Builder setSort(List<String> sort) {
+ this.sort = Optional.of(sort);
+ return this;
+ }
- @JsonProperty
- public int getTopN() {
- return topN;
- }
+ public Builder setCounts(final List<String> counts) {
+ this.counts = Optional.of(counts);
+ return this;
+ }
- public void setAfter(final PrimitiveWrapper<?>[] after) {
- this.after = after;
- }
+ public Builder setRanges(final Map<String, List<DoubleRange>> ranges) {
+ this.ranges = Optional.of(ranges);
+ return this;
+ }
- @JsonProperty
- public PrimitiveWrapper<?>[] getAfter() {
- return after;
- }
+ public Builder setTopN(final int topN) {
+ this.topN = OptionalInt.of(topN);
+ return this;
+ }
+
+ public Builder setAfter(final PrimitiveWrapper<?>[] after) {
+ this.after = Optional.of(after);
+ return this;
+ }
- @Override
- public String toString() {
- return "SearchRequest [query=" + query + ", min_update_seq=" + minUpdateSeq + ", min_purge_seq=" + minPurgeSeq
- + ", locale=" + locale + ", sort=" + sort + ", limit=" + limit + ", after=" + after + ", counts="
- + counts + ", ranges=" + ranges + "]";
+ public SearchRequest build() {
+ return new SearchRequest(
+ query, minUpdateSeq, minPurgeSeq, locale, partition, limit, sort, counts, ranges, after, topN);
+ }
}
}
diff --git a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/api/SearchResults.java b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/api/SearchResults.java
index a273e6ef2..dec725e8a 100644
--- a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/api/SearchResults.java
+++ b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/api/SearchResults.java
@@ -13,7 +13,6 @@
package org.apache.couchdb.nouveau.api;
-import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import jakarta.validation.constraints.NotNull;
@@ -23,70 +22,9 @@ import java.util.Map;
import org.apache.lucene.search.TotalHits.Relation;
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
-public class SearchResults {
-
- @PositiveOrZero
- private long totalHits;
-
- @NotNull
- private Relation totalHitsRelation;
-
- @NotNull
- private List<@NotNull SearchHit> hits;
-
- private Map<@NotNull String, Map<@NotNull String, Number>> counts;
-
- private Map<@NotNull String, Map<@NotNull String, Number>> ranges;
-
- public SearchResults() {}
-
- public void setTotalHits(final long totalHits) {
- this.totalHits = totalHits;
- }
-
- @JsonProperty
- public long getTotalHits() {
- return totalHits;
- }
-
- public Relation getTotalHitsRelation() {
- return totalHitsRelation;
- }
-
- public void setTotalHitsRelation(Relation relation) {
- this.totalHitsRelation = relation;
- }
-
- public void setHits(final List<SearchHit> hits) {
- this.hits = hits;
- }
-
- @JsonProperty
- public List<SearchHit> getHits() {
- return hits;
- }
-
- public void setCounts(final Map<String, Map<String, Number>> counts) {
- this.counts = counts;
- }
-
- @JsonProperty
- public Map<String, Map<String, Number>> getCounts() {
- return counts;
- }
-
- public void setRanges(final Map<String, Map<String, Number>> ranges) {
- this.ranges = ranges;
- }
-
- @JsonProperty
- public Map<String, Map<String, Number>> getRanges() {
- return ranges;
- }
-
- @Override
- public String toString() {
- return "SearchResults [hits=" + hits + ", totalHits=" + totalHits + ", counts=" + counts + ", ranges=" + ranges
- + "]";
- }
-}
+public record SearchResults(
+ @PositiveOrZero long totalHits,
+ @NotNull Relation totalHitsRelation,
+ @NotNull List<@NotNull SearchHit> hits,
+ Map<@NotNull String, Map<@NotNull String, Number>> counts,
+ Map<@NotNull String, Map<@NotNull String, Number>> ranges) {}
diff --git a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/core/Index.java b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/core/Index.java
index e7693702c..c90cc6aaa 100644
--- a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/core/Index.java
+++ b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/core/Index.java
@@ -77,7 +77,7 @@ public abstract class Index implements Closeable {
protected abstract void doDelete(final String docId, final DocumentDeleteRequest request) throws IOException;
public final SearchResults search(final SearchRequest request) throws IOException {
- assertMinSeqs(request.getMinUpdateSeq(), request.getMinPurgeSeq());
+ assertMinSeqs(request.minUpdateSeq(), request.minPurgeSeq());
return doSearch(request);
}
diff --git a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/health/IndexHealthCheck.java b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/health/IndexHealthCheck.java
index 81bca3094..5b4e7beb8 100644
--- a/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/health/IndexHealthCheck.java
+++ b/extra/nouveau/src/main/java/org/apache/couchdb/nouveau/health/IndexHealthCheck.java
@@ -53,16 +53,16 @@ public final class IndexHealthCheck extends HealthCheck {
name,
new BulkUpdateRequest(List.of(new DocumentUpdate(
"foo", new DocumentUpdateRequest(0, 1, null, Collections.emptyList())))));
- final SearchRequest searchRequest = new SearchRequest();
- searchRequest.setQuery("_id:foo");
- searchRequest.setMinUpdateSeq(1);
-
+ final SearchRequest searchRequest = new SearchRequest.Builder()
+ .setQuery("_id:foo")
+ .setMinUpdateSeq(1)
+ .build();
final SearchResults searchResults = indexResource.searchIndex(name, searchRequest);
- if (searchResults.getTotalHits() == 1) {
+ if (searchResults.totalHits() == 1) {
return Result.healthy();
} else {
return Result.unhealthy(
- "Wrong number of search results, expected 1, got %d", searchResults.getTotalHits());
+ "Wrong number of search results, expected 1, got %d", searchResults.totalHits());
}
} finally {
indexResource.deletePath(name, null);
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 1f6a735ff..14cc672e9 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
@@ -25,9 +25,9 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.NoSuchFileException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
@@ -223,21 +223,20 @@ public class LuceneIndex extends Index {
private CollectorManager<?, ? extends TopDocs> hitCollector(final SearchRequest searchRequest) {
final Sort sort = toSort(searchRequest);
+ final FieldDoc fieldDoc = searchRequest
+ .after()
+ .map(after -> {
+ var result = toFieldDoc(after);
+ if (getLastSortField(sort).getReverse()) {
+ result.doc = 0;
+ } else {
+ result.doc = Integer.MAX_VALUE;
+ }
+ return result;
+ })
+ .orElse(null);
- final PrimitiveWrapper<?>[] after = searchRequest.getAfter();
- final FieldDoc fieldDoc;
- if (after != null) {
- fieldDoc = toFieldDoc(after);
- if (getLastSortField(sort).getReverse()) {
- fieldDoc.doc = 0;
- } else {
- fieldDoc.doc = Integer.MAX_VALUE;
- }
- } else {
- fieldDoc = null;
- }
-
- return new TopFieldCollectorManager(sort, searchRequest.getLimit(), fieldDoc, 1000);
+ return new TopFieldCollectorManager(sort, searchRequest.limitAsInt(), fieldDoc, 1000);
}
private SortField getLastSortField(final Sort sort) {
@@ -248,17 +247,20 @@ public class LuceneIndex extends Index {
private SearchResults toSearchResults(
final SearchRequest searchRequest, final IndexSearcher searcher, final Object[] reduces)
throws IOException {
- final SearchResults result = new SearchResults();
- collectHits(searcher, (TopDocs) reduces[0], result);
+ final TopDocs topDocs = (TopDocs) reduces[0];
+ final var hits = collectHits(searcher, topDocs);
+ Map<String, Map<String, Number>> counts = Collections.emptyMap();
+ Map<String, Map<String, Number>> ranges = Collections.emptyMap();
+
if (reduces.length == 2) {
- collectFacets(searchRequest, searcher, (FacetsCollector) reduces[1], result);
+ counts = collectCounts(searchRequest, searcher, (FacetsCollector) reduces[1]);
+ ranges = collectRanges(searchRequest, searcher, (FacetsCollector) reduces[1]);
}
- return result;
+ return new SearchResults(topDocs.totalHits.value(), topDocs.totalHits.relation(), hits, counts, ranges);
}
- private void collectHits(final IndexSearcher searcher, final TopDocs topDocs, final SearchResults searchResults)
- throws IOException {
- final List<SearchHit> hits = new ArrayList<SearchHit>(topDocs.scoreDocs.length);
+ private List<SearchHit> collectHits(final IndexSearcher searcher, final TopDocs topDocs) throws IOException {
+ final List<SearchHit> result = new ArrayList<SearchHit>(topDocs.scoreDocs.length);
final StoredFields storedFields = searcher.storedFields();
for (final ScoreDoc scoreDoc : topDocs.scoreDocs) {
@@ -287,42 +289,40 @@ public class LuceneIndex extends Index {
}
final PrimitiveWrapper<?>[] after = toAfter(((FieldDoc) scoreDoc));
- hits.add(new SearchHit(doc.get("_id"), after, fields));
+ result.add(new SearchHit(doc.get("_id"), after, fields));
}
-
- searchResults.setTotalHits(topDocs.totalHits.value());
- searchResults.setTotalHitsRelation(topDocs.totalHits.relation());
- searchResults.setHits(hits);
+ return result;
}
- private void collectFacets(
- final SearchRequest searchRequest,
- final IndexSearcher searcher,
- final FacetsCollector fc,
- final SearchResults searchResults)
+ private Map<String, Map<String, Number>> collectCounts(
+ final SearchRequest searchRequest, final IndexSearcher searcher, final FacetsCollector fc)
throws IOException {
- if (searchRequest.hasCounts()) {
- final Map<String, Map<String, Number>> countsMap = new HashMap<String, Map<String, Number>>(
- searchRequest.getCounts().size());
- for (final String field : searchRequest.getCounts()) {
- final StringDocValuesReaderState state =
- new StringDocValuesReaderState(searcher.getIndexReader(), field);
- final StringValueFacetCounts counts = new StringValueFacetCounts(state, fc);
- countsMap.put(field, collectFacets(counts, searchRequest.getTopN(), field));
- }
- searchResults.setCounts(countsMap);
+ if (!searchRequest.hasCounts()) {
+ return Collections.emptyMap();
+ }
+ var c = searchRequest.counts().get();
+ final Map<String, Map<String, Number>> result = new HashMap<String, Map<String, Number>>(c.size());
+ for (final String field : c) {
+ final StringDocValuesReaderState state = new StringDocValuesReaderState(searcher.getIndexReader(), field);
+ final StringValueFacetCounts counts = new StringValueFacetCounts(state, fc);
+ result.put(field, collectFacets(counts, searchRequest.topNAsInt(), field));
}
+ return result;
+ }
- if (searchRequest.hasRanges()) {
- final Map<String, Map<String, Number>> rangesMap = new HashMap<String, Map<String, Number>>(
- searchRequest.getRanges().size());
- for (final Entry<String, List<DoubleRange>> entry :
- searchRequest.getRanges().entrySet()) {
- final DoubleRangeFacetCounts counts = toDoubleRangeFacetCounts(fc, entry.getKey(), entry.getValue());
- rangesMap.put(entry.getKey(), collectFacets(counts, searchRequest.getTopN(), entry.getKey()));
- }
- searchResults.setRanges(rangesMap);
+ private Map<String, Map<String, Number>> collectRanges(
+ final SearchRequest searchRequest, final IndexSearcher searcher, final FacetsCollector fc)
+ throws IOException {
+ if (!searchRequest.hasRanges()) {
+ return Collections.emptyMap();
}
+ var r = searchRequest.ranges().get();
+ final Map<String, Map<String, Number>> result = new HashMap<String, Map<String, Number>>(r.size());
+ for (final Entry<String, List<DoubleRange>> entry : r.entrySet()) {
+ final DoubleRangeFacetCounts counts = toDoubleRangeFacetCounts(fc, entry.getKey(), entry.getValue());
+ result.put(entry.getKey(), collectFacets(counts, searchRequest.topNAsInt(), entry.getKey()));
+ }
+ return result;
}
private DoubleRangeFacetCounts toDoubleRangeFacetCounts(
@@ -353,21 +353,22 @@ public class LuceneIndex extends Index {
// Ensure _id is final sort field so we can paginate.
private Sort toSort(final SearchRequest searchRequest) {
- if (!searchRequest.hasSort()) {
- return DEFAULT_SORT;
- }
-
- final List<String> sort = new ArrayList<String>(searchRequest.getSort());
- final String last = sort.get(sort.size() - 1);
- // Append _id field if not already present.
- switch (last) {
- case "-_id":
- case "_id":
- break;
- default:
- sort.add("_id");
- }
- return convertSort(sort);
+ return searchRequest
+ .sort()
+ .map(s -> {
+ final List<String> sort = new ArrayList<String>(s);
+ final String last = sort.get(sort.size() - 1);
+ // Append _id field if not already present.
+ switch (last) {
+ case "-_id":
+ case "_id":
+ break;
+ default:
+ sort.add("_id");
+ }
+ return convertSort(sort);
+ })
+ .orElse(DEFAULT_SORT);
}
private Sort convertSort(final List<String> sort) {
@@ -518,23 +519,22 @@ public class LuceneIndex extends Index {
}
private Query parse(final SearchRequest request) {
- var locale = request.getLocale() != null ? request.getLocale() : Locale.getDefault();
- var pointsConfigMap = schema.toPointsConfigMap(locale);
+ var pointsConfigMap = schema.toPointsConfigMap(request.getLocale());
var queryParser = new NouveauQueryParser(analyzer, pointsConfigMap);
- Query result;
try {
- result = queryParser.parse(request.getQuery(), "default");
- if (request.hasPartition()) {
- final BooleanQuery.Builder builder = new BooleanQuery.Builder();
- builder.add(new TermQuery(new Term("_partition", request.getPartition())), Occur.MUST);
- builder.add(result, Occur.MUST);
- result = builder.build();
- }
+ var result = queryParser.parse(request.query(), "default");
+ return request.partition()
+ .map(partition -> {
+ final BooleanQuery.Builder builder = new BooleanQuery.Builder();
+ builder.add(new TermQuery(new Term("_partition", partition)), Occur.MUST);
+ builder.add(result, Occur.MUST);
+ return (Query) builder.build();
+ })
+ .orElse(result);
} catch (final QueryNodeException e) {
throw new WebApplicationException(e.getMessage(), e, Status.BAD_REQUEST);
}
- return result;
}
private LuceneIndexSchema initSchema(IndexWriter writer) {
diff --git a/extra/nouveau/src/test/java/org/apache/couchdb/nouveau/api/SearchRequestTest.java b/extra/nouveau/src/test/java/org/apache/couchdb/nouveau/api/SearchRequestTest.java
index 9269f11e8..9c02589d8 100644
--- a/extra/nouveau/src/test/java/org/apache/couchdb/nouveau/api/SearchRequestTest.java
+++ b/extra/nouveau/src/test/java/org/apache/couchdb/nouveau/api/SearchRequestTest.java
@@ -28,6 +28,7 @@ public class SearchRequestTest {
@BeforeAll
public static void setupMapper() {
mapper = new ObjectMapper();
+ mapper.findAndRegisterModules();
}
@Test
@@ -47,12 +48,12 @@ public class SearchRequestTest {
}
private SearchRequest asObject() {
- final SearchRequest result = new SearchRequest();
- result.setQuery("*:*");
- result.setLimit(10);
- result.setCounts(List.of("bar"));
- result.setTopN(5);
- result.setRanges(Map.of("foo", List.of(new DoubleRange("0 to 100 inc", 0.0, true, 100.0, true))));
- return result;
+ return new SearchRequest.Builder()
+ .setQuery("*:*")
+ .setLimit(10)
+ .setCounts(List.of("bar"))
+ .setTopN(5)
+ .setRanges(Map.of("foo", List.of(new DoubleRange("0 to 100 inc", 0.0, true, 100.0, true))))
+ .build();
}
}
diff --git a/extra/nouveau/src/test/java/org/apache/couchdb/nouveau/core/IndexManagerTest.java b/extra/nouveau/src/test/java/org/apache/couchdb/nouveau/core/IndexManagerTest.java
index e1d867bd2..b76ff1268 100644
--- a/extra/nouveau/src/test/java/org/apache/couchdb/nouveau/core/IndexManagerTest.java
+++ b/extra/nouveau/src/test/java/org/apache/couchdb/nouveau/core/IndexManagerTest.java
@@ -66,10 +66,9 @@ public class IndexManagerTest {
public void managerReturnsUsableIndex() throws Exception {
final IndexDefinition indexDefinition = new IndexDefinition();
manager.create("foo", indexDefinition);
- var searchRequest = new SearchRequest();
- searchRequest.setQuery("*:*");
+ var searchRequest = new SearchRequest.Builder().setQuery("*:*").build();
var searchResults = manager.with("foo", (index) -> index.search(searchRequest));
- assertThat(searchResults.getTotalHits()).isEqualTo(0);
+ assertThat(searchResults.totalHits()).isEqualTo(0);
}
@Test
diff --git a/extra/nouveau/src/test/java/org/apache/couchdb/nouveau/lucene/LuceneIndexTest.java b/extra/nouveau/src/test/java/org/apache/couchdb/nouveau/lucene/LuceneIndexTest.java
index 83ee15268..e8375184f 100644
--- a/extra/nouveau/src/test/java/org/apache/couchdb/nouveau/lucene/LuceneIndexTest.java
+++ b/extra/nouveau/src/test/java/org/apache/couchdb/nouveau/lucene/LuceneIndexTest.java
@@ -79,11 +79,12 @@ public class LuceneIndexTest {
final DocumentUpdateRequest request = new DocumentUpdateRequest(i - 1, i, null, fields);
index.update("doc" + i, request);
}
- final SearchRequest request = new SearchRequest();
- request.setMinUpdateSeq(count);
- request.setQuery("*:*");
+ final SearchRequest request = new SearchRequest.Builder()
+ .setMinUpdateSeq(count)
+ .setQuery("*:*")
+ .build();
final SearchResults results = index.search(request);
- assertThat(results.getTotalHits()).isEqualTo(count);
+ assertThat(results.totalHits()).isEqualTo(count);
} finally {
cleanup(index);
}
@@ -99,12 +100,13 @@ public class LuceneIndexTest {
final DocumentUpdateRequest request = new DocumentUpdateRequest(i - 1, i, null, fields);
index.update("doc" + i, request);
}
- final SearchRequest request = new SearchRequest();
- request.setMinUpdateSeq(count);
- request.setQuery("*:*");
- request.setSort(List.of("foo"));
+ final SearchRequest request = new SearchRequest.Builder()
+ .setMinUpdateSeq(count)
+ .setQuery("*:*")
+ .setSort(List.of("foo"))
+ .build();
final SearchResults results = index.search(request);
- assertThat(results.getTotalHits()).isEqualTo(count);
+ assertThat(results.totalHits()).isEqualTo(count);
} finally {
cleanup(index);
}
@@ -120,12 +122,13 @@ public class LuceneIndexTest {
final DocumentUpdateRequest request = new DocumentUpdateRequest(i - 1, i, null, fields);
index.update("doc" + i, request);
}
- final SearchRequest request = new SearchRequest();
- request.setMinUpdateSeq(count);
- request.setQuery("*:*");
- request.setCounts(List.of("bar"));
+ final SearchRequest request = new SearchRequest.Builder()
+ .setMinUpdateSeq(count)
+ .setQuery("*:*")
+ .setCounts(List.of("bar"))
+ .build();
final SearchResults results = index.search(request);
- assertThat(results.getCounts()).isEqualTo(Map.of("bar", Map.of("baz", count)));
+ assertThat(results.counts()).isEqualTo(Map.of("bar", Map.of("baz", count)));
} finally {
cleanup(index);
}
@@ -141,16 +144,17 @@ public class LuceneIndexTest {
final DocumentUpdateRequest request = new DocumentUpdateRequest(i - 1, i, null, fields);
index.update("doc" + i, request);
}
- final SearchRequest request = new SearchRequest();
- request.setMinUpdateSeq(count);
- request.setQuery("*:*");
- request.setRanges(Map.of(
- "bar",
- List.of(
- new DoubleRange("low", 0.0, true, (double) count / 2, true),
- new DoubleRange("high", (double) count / 2, true, (double) count, true))));
+ final SearchRequest request = new SearchRequest.Builder()
+ .setMinUpdateSeq(count)
+ .setQuery("*:*")
+ .setRanges(Map.of(
+ "bar",
+ List.of(
+ new DoubleRange("low", 0.0, true, (double) count / 2, true),
+ new DoubleRange("high", (double) count / 2, true, (double) count, true))))
+ .build();
final SearchResults results = index.search(request);
- assertThat(results.getRanges()).isEqualTo(Map.of("bar", Map.of("low", count / 2, "high", count / 2 + 1)));
+ assertThat(results.ranges()).isEqualTo(Map.of("bar", Map.of("low", count / 2, "high", count / 2 + 1)));
} finally {
cleanup(index);
}
@@ -173,13 +177,14 @@ public class LuceneIndexTest {
index.update("doc" + i, request);
}
- final SearchRequest request = new SearchRequest();
- request.setMinUpdateSeq(count);
- request.setQuery("*:*");
- request.setCounts(List.of("bar"));
- request.setTopN(1);
+ final SearchRequest request = new SearchRequest.Builder()
+ .setMinUpdateSeq(count)
+ .setQuery("*:*")
+ .setCounts(List.of("bar"))
+ .setTopN(1)
+ .build();
final SearchResults results = index.search(request);
- assertThat(results.getCounts()).isEqualTo(Map.of("bar", Map.of("baz", count + 5)));
+ assertThat(results.counts()).isEqualTo(Map.of("bar", Map.of("baz", count + 5)));
} finally {
cleanup(index);
}
@@ -214,9 +219,10 @@ public class LuceneIndexTest {
try {
// Require min seq 1 on new, empty index should fail.
assertThrows(StaleIndexException.class, () -> {
- final SearchRequest request = new SearchRequest();
- request.setMinUpdateSeq(1);
- request.setQuery("*:*");
+ final SearchRequest request = new SearchRequest.Builder()
+ .setMinUpdateSeq(1)
+ .setQuery("*:*")
+ .build();
index.search(request);
});
} finally {