Replace scoreMode with boolean "complete"
This commit is contained in:
parent
5817d8a93f
commit
d6b6a211a8
@ -179,7 +179,7 @@ versions:
|
||||
limit: long
|
||||
minCompetitiveScore: -float
|
||||
sort: Sort
|
||||
scoreMode: ScoreMode
|
||||
complete: boolean
|
||||
NoSort:
|
||||
data: { }
|
||||
NumericSort:
|
||||
@ -192,10 +192,6 @@ versions:
|
||||
data: { }
|
||||
DocSort:
|
||||
data: { }
|
||||
ScoreMode:
|
||||
data:
|
||||
onlyTopScores: boolean
|
||||
computeScores: boolean
|
||||
TotalHitsCount:
|
||||
stringRepresenter: "it.cavallium.dbengine.lucene.LuceneUtils.toHumanReadableString"
|
||||
data:
|
||||
|
@ -1,5 +1,6 @@
|
||||
package it.cavallium.dbengine.client;
|
||||
|
||||
import it.cavallium.dbengine.client.query.BasicType;
|
||||
import it.cavallium.dbengine.client.query.current.data.DocSort;
|
||||
import it.cavallium.dbengine.client.query.current.data.NoSort;
|
||||
import it.cavallium.dbengine.client.query.current.data.NumericSort;
|
||||
@ -24,6 +25,10 @@ public class MultiSort<T> {
|
||||
this.querySort = querySort;
|
||||
}
|
||||
|
||||
public boolean isSorted() {
|
||||
return querySort.getBasicType$() != BasicType.NoSort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort a lucene field and the results by a numeric sort field and an int value
|
||||
* @param fieldName Lucene SortedNumericSortField field name
|
||||
|
@ -8,7 +8,6 @@ import it.cavallium.dbengine.client.query.current.data.NoSort;
|
||||
import it.cavallium.dbengine.client.query.current.data.Query;
|
||||
import it.cavallium.dbengine.client.query.current.data.QueryParams;
|
||||
import it.cavallium.dbengine.client.query.current.data.QueryParamsBuilder;
|
||||
import it.cavallium.dbengine.client.query.current.data.ScoreMode;
|
||||
import it.cavallium.dbengine.database.LLScoreMode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -20,7 +19,7 @@ public final record ClientQueryParams<T>(@Nullable CompositeSnapshot snapshot,
|
||||
long limit,
|
||||
@Nullable Float minCompetitiveScore,
|
||||
@Nullable MultiSort<T> sort,
|
||||
@NotNull LLScoreMode scoreMode) {
|
||||
boolean complete) {
|
||||
|
||||
public static <T> ClientQueryParamsBuilder<T> builder() {
|
||||
return ClientQueryParamsBuilder
|
||||
@ -30,29 +29,22 @@ public final record ClientQueryParams<T>(@Nullable CompositeSnapshot snapshot,
|
||||
.limit(Long.MAX_VALUE)
|
||||
.minCompetitiveScore(null)
|
||||
.sort(null)
|
||||
.scoreMode(LLScoreMode.COMPLETE);
|
||||
.complete(true);
|
||||
}
|
||||
|
||||
public ScoreMode toScoreMode() {
|
||||
return switch (this.scoreMode()) {
|
||||
case COMPLETE -> ScoreMode.of(false, true);
|
||||
case COMPLETE_NO_SCORES -> ScoreMode.of(false, false);
|
||||
case TOP_SCORES -> ScoreMode.of(true, true);
|
||||
case NO_SCORES -> ScoreMode.of(true, false);
|
||||
//noinspection UnnecessaryDefault
|
||||
default -> throw new IllegalArgumentException();
|
||||
};
|
||||
public boolean isSorted() {
|
||||
return sort != null && sort.isSorted();
|
||||
}
|
||||
|
||||
public QueryParams toQueryParams() {
|
||||
return QueryParamsBuilder
|
||||
.builder()
|
||||
.query(query())
|
||||
.sort(sort() != null ? sort().getQuerySort() : NoSort.of())
|
||||
.sort(sort != null ? sort.getQuerySort() : new NoSort())
|
||||
.minCompetitiveScore(Nullablefloat.ofNullable(minCompetitiveScore()))
|
||||
.offset(offset())
|
||||
.limit(limit())
|
||||
.scoreMode(toScoreMode())
|
||||
.complete(complete())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
@ -132,10 +132,6 @@ public class QueryParser {
|
||||
return new Term(term.field(), term.value());
|
||||
}
|
||||
|
||||
public static boolean isScoringEnabled(QueryParams queryParams) {
|
||||
return queryParams.scoreMode().computeScores();
|
||||
}
|
||||
|
||||
public static Sort toSort(it.cavallium.dbengine.client.query.current.data.Sort sort) {
|
||||
switch (sort.getBasicType$()) {
|
||||
case NoSort:
|
||||
@ -154,21 +150,6 @@ public class QueryParser {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public static ScoreMode toScoreMode(it.cavallium.dbengine.client.query.current.data.ScoreMode scoreMode) {
|
||||
if (scoreMode.computeScores() && scoreMode.onlyTopScores()) {
|
||||
return ScoreMode.TOP_SCORES;
|
||||
} else if (scoreMode.computeScores() && !scoreMode.onlyTopScores()) {
|
||||
return ScoreMode.COMPLETE;
|
||||
} else if (!scoreMode.computeScores() && scoreMode.onlyTopScores()) {
|
||||
return ScoreMode.TOP_DOCS;
|
||||
} else if (!scoreMode.computeScores() && !scoreMode.onlyTopScores()) {
|
||||
return ScoreMode.COMPLETE_NO_SCORES;
|
||||
} else {
|
||||
throw new IllegalStateException("Unexpected value: " + scoreMode);
|
||||
}
|
||||
}
|
||||
|
||||
public static it.cavallium.dbengine.client.query.current.data.Term toQueryTerm(Term term) {
|
||||
return it.cavallium.dbengine.client.query.current.data.Term.of(term.field(), term.text());
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import it.cavallium.data.generator.nativedata.Nullablefloat;
|
||||
import it.cavallium.dbengine.client.query.current.data.NoSort;
|
||||
import it.cavallium.dbengine.client.query.current.data.Query;
|
||||
import it.cavallium.dbengine.client.query.current.data.QueryParams;
|
||||
import it.cavallium.dbengine.client.query.current.data.ScoreMode;
|
||||
import it.cavallium.dbengine.client.query.current.data.TotalHitsCount;
|
||||
import it.cavallium.dbengine.lucene.LuceneUtils;
|
||||
import java.util.List;
|
||||
@ -54,7 +53,7 @@ public interface LLLuceneIndex extends LLSnapshottable {
|
||||
Mono<Send<LLSearchResultShard>> search(@Nullable LLSnapshot snapshot, QueryParams queryParams, String keyFieldName);
|
||||
|
||||
default Mono<TotalHitsCount> count(@Nullable LLSnapshot snapshot, Query query) {
|
||||
QueryParams params = QueryParams.of(query, 0, 0, Nullablefloat.empty(), NoSort.of(), ScoreMode.of(false, false));
|
||||
QueryParams params = QueryParams.of(query, 0, 0, Nullablefloat.empty(), NoSort.of(), false);
|
||||
return Mono.from(this.search(snapshot, params, null)
|
||||
.map(llSearchResultShardToReceive -> {
|
||||
try (var llSearchResultShard = llSearchResultShardToReceive.receive()) {
|
||||
|
@ -347,7 +347,7 @@ public class LuceneUtils {
|
||||
DEFAULT_PAGE_LIMITS,
|
||||
queryParams.minCompetitiveScore().getNullable(),
|
||||
QueryParser.toSort(queryParams.sort()),
|
||||
QueryParser.toScoreMode(queryParams.scoreMode())
|
||||
queryParams.complete()
|
||||
);
|
||||
}
|
||||
|
||||
@ -453,8 +453,8 @@ public class LuceneUtils {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int totalHitsThreshold() {
|
||||
return 1;
|
||||
public static int totalHitsThreshold(boolean complete) {
|
||||
return complete ? Integer.MAX_VALUE : 1;
|
||||
}
|
||||
|
||||
public static TotalHitsCount convertTotalHitsCount(TotalHits totalHits) {
|
||||
@ -503,7 +503,7 @@ public class LuceneUtils {
|
||||
DEFAULT_PAGE_LIMITS,
|
||||
localQueryParams.minCompetitiveScore(),
|
||||
localQueryParams.sort(),
|
||||
localQueryParams.scoreMode()
|
||||
localQueryParams.complete()
|
||||
);
|
||||
}
|
||||
MultiMoreLikeThis mlt;
|
||||
@ -521,7 +521,7 @@ public class LuceneUtils {
|
||||
mlt.setMinTermFreq(1);
|
||||
mlt.setMinDocFreq(3);
|
||||
mlt.setMaxDocFreqPct(20);
|
||||
mlt.setBoost(localQueryParams.scoreMode().needsScores());
|
||||
mlt.setBoost(localQueryParams.needsScores());
|
||||
mlt.setStopWords(EnglishItalianStopFilter.getStopWordsString());
|
||||
if (similarity instanceof TFIDFSimilarity tfidfSimilarity) {
|
||||
mlt.setSimilarity(tfidfSimilarity);
|
||||
@ -548,7 +548,7 @@ public class LuceneUtils {
|
||||
DEFAULT_PAGE_LIMITS,
|
||||
localQueryParams.minCompetitiveScore(),
|
||||
localQueryParams.sort(),
|
||||
localQueryParams.scoreMode()
|
||||
localQueryParams.complete()
|
||||
);
|
||||
}).subscribeOn(Schedulers.boundedElastic()));
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ public class AdaptiveMultiSearcher implements MultiSearcher, Closeable {
|
||||
return LLUtils.usingSendResource(indexSearchersMono, indexSearchers -> {
|
||||
if (queryParams.limit() == 0) {
|
||||
return count.collectMulti(indexSearchersMono, queryParams, keyFieldName, transformer);
|
||||
} else if (queryParams.isSorted() || queryParams.isScored()) {
|
||||
} else if (queryParams.isSorted() || queryParams.needsScores()) {
|
||||
if (queryParams.isSorted() || realLimit <= (long) queryParams.pageLimits().getPageLimit(0)) {
|
||||
return scoredSimple.collectMulti(indexSearchersMono, queryParams, keyFieldName, transformer);
|
||||
} else {
|
||||
|
@ -1,6 +1,8 @@
|
||||
package it.cavallium.dbengine.lucene.searcher;
|
||||
|
||||
import it.cavallium.dbengine.lucene.LuceneUtils;
|
||||
import it.cavallium.dbengine.lucene.PageLimits;
|
||||
import java.util.Optional;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.ScoreMode;
|
||||
import org.apache.lucene.search.Sort;
|
||||
@ -8,14 +10,38 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public record LocalQueryParams(@NotNull Query query, int offset, int limit, @NotNull PageLimits pageLimits,
|
||||
@Nullable Float minCompetitiveScore, @Nullable Sort sort,
|
||||
@NotNull ScoreMode scoreMode) {
|
||||
@Nullable Float minCompetitiveScore, @Nullable Sort sort, boolean complete) {
|
||||
|
||||
public boolean isSorted() {
|
||||
return sort != null;
|
||||
}
|
||||
|
||||
public boolean isScored() {
|
||||
return (sort != null && sort.needsScores()) || scoreMode.needsScores();
|
||||
public boolean needsScores() {
|
||||
return sort != null && sort.needsScores();
|
||||
}
|
||||
|
||||
public Optional<Boolean> needsScoresOptional() {
|
||||
if (sort == null) return Optional.empty();
|
||||
return Optional.of(sort.needsScores());
|
||||
}
|
||||
|
||||
public ScoreMode getScoreMode() {
|
||||
if (complete) {
|
||||
return needsScores() ? ScoreMode.COMPLETE : ScoreMode.COMPLETE_NO_SCORES;
|
||||
} else {
|
||||
return needsScores() ? ScoreMode.TOP_DOCS_WITH_SCORES : ScoreMode.TOP_DOCS;
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<ScoreMode> getScoreModeOptional() {
|
||||
if (complete) {
|
||||
return needsScoresOptional().map(needsScores -> needsScores ? ScoreMode.COMPLETE : ScoreMode.COMPLETE_NO_SCORES);
|
||||
} else {
|
||||
return needsScoresOptional().map(needsScores -> needsScores ? ScoreMode.TOP_DOCS_WITH_SCORES : ScoreMode.TOP_DOCS);
|
||||
}
|
||||
}
|
||||
|
||||
public int getTotalHitsThreshold() {
|
||||
return LuceneUtils.totalHitsThreshold(this.complete);
|
||||
}
|
||||
}
|
||||
|
@ -33,8 +33,6 @@ public class PagedLocalSearcher implements LocalSearcher {
|
||||
LocalQueryParams queryParams,
|
||||
String keyFieldName,
|
||||
LLSearchTransformer transformer) {
|
||||
|
||||
Objects.requireNonNull(queryParams.scoreMode(), "ScoreMode must not be null");
|
||||
PaginationInfo paginationInfo = getPaginationInfo(queryParams);
|
||||
|
||||
var indexSearchersMono = indexSearcherMono.map(LLIndexSearchers::unsharded).map(ResourceSupport::send);
|
||||
@ -185,8 +183,13 @@ public class PagedLocalSearcher implements LocalSearcher {
|
||||
TopDocs pageTopDocs;
|
||||
try {
|
||||
TopDocsCollector<ScoreDoc> collector = TopDocsCollectorUtils.getTopDocsCollector(queryParams.sort(),
|
||||
currentPageLimit, s.last(), LuceneUtils.totalHitsThreshold(),
|
||||
allowPagination, queryParams.isScored());
|
||||
currentPageLimit, s.last(), queryParams.getTotalHitsThreshold(),
|
||||
allowPagination, queryParams.needsScores());
|
||||
assert queryParams.complete() == collector.scoreMode().isExhaustive();
|
||||
queryParams.getScoreModeOptional().ifPresent(scoreMode -> {
|
||||
assert scoreMode == collector.scoreMode();
|
||||
});
|
||||
|
||||
indexSearchers.get(0).search(queryParams.query(), collector);
|
||||
if (resultsOffset > 0) {
|
||||
pageTopDocs = collector.topDocs(resultsOffset, currentPageLimit);
|
||||
|
@ -16,6 +16,7 @@ import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.apache.lucene.search.FieldDoc;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.ScoreMode;
|
||||
import org.apache.lucene.search.Sort;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.warp.commonutils.log.Logger;
|
||||
@ -45,7 +46,6 @@ public class ScoredPagedMultiSearcher implements MultiSearcher {
|
||||
}
|
||||
|
||||
return queryParamsMono.flatMap(queryParams2 -> {
|
||||
Objects.requireNonNull(queryParams2.scoreMode(), "ScoreMode must not be null");
|
||||
PaginationInfo paginationInfo = getPaginationInfo(queryParams2);
|
||||
|
||||
return LLUtils.usingSendResource(indexSearchersMono, indexSearchers -> this
|
||||
@ -175,7 +175,7 @@ public class ScoredPagedMultiSearcher implements MultiSearcher {
|
||||
@Nullable var sort = getSort(queryParams);
|
||||
var pageLimit = pageLimits.getPageLimit(s.pageIndex());
|
||||
var after = (FieldDoc) s.last();
|
||||
var totalHitsThreshold = LuceneUtils.totalHitsThreshold();
|
||||
var totalHitsThreshold = queryParams.getTotalHitsThreshold();
|
||||
return new ScoringShardsCollectorManager(sort, pageLimit, after, totalHitsThreshold,
|
||||
resultsOffset);
|
||||
} else {
|
||||
@ -186,7 +186,13 @@ public class ScoredPagedMultiSearcher implements MultiSearcher {
|
||||
.fromIterable(indexSearchers)
|
||||
.flatMap(shard -> Mono.fromCallable(() -> {
|
||||
LLUtils.ensureBlocking();
|
||||
|
||||
var collector = sharedManager.newCollector();
|
||||
assert queryParams.complete() == collector.scoreMode().isExhaustive();
|
||||
queryParams.getScoreModeOptional().ifPresent(scoreMode -> {
|
||||
assert scoreMode == collector.scoreMode();
|
||||
});
|
||||
|
||||
shard.search(queryParams.query(), collector);
|
||||
return collector;
|
||||
}))
|
||||
|
@ -44,8 +44,7 @@ public class UnsortedScoredFullMultiSearcher implements MultiSearcher, Closeable
|
||||
}
|
||||
|
||||
return queryParamsMono.flatMap(queryParams2 -> {
|
||||
Objects.requireNonNull(queryParams2.scoreMode(), "ScoreMode must not be null");
|
||||
if (queryParams2.sort() != null && queryParams2.sort() != Sort.RELEVANCE) {
|
||||
if (queryParams2.isSorted()) {
|
||||
throw new IllegalArgumentException(UnsortedScoredFullMultiSearcher.this.getClass().getSimpleName()
|
||||
+ " doesn't support sorted queries");
|
||||
}
|
||||
@ -70,14 +69,20 @@ public class UnsortedScoredFullMultiSearcher implements MultiSearcher, Closeable
|
||||
return Mono
|
||||
.fromCallable(() -> {
|
||||
LLUtils.ensureBlocking();
|
||||
var totalHitsThreshold = LuceneUtils.totalHitsThreshold();
|
||||
var totalHitsThreshold = queryParams.getTotalHitsThreshold();
|
||||
return LMDBFullScoreDocCollector.createSharedManager(env, totalHitsThreshold);
|
||||
})
|
||||
.flatMap(sharedManager -> Flux
|
||||
.fromIterable(indexSearchers)
|
||||
.flatMap(shard -> Mono.fromCallable(() -> {
|
||||
LLUtils.ensureBlocking();
|
||||
|
||||
var collector = sharedManager.newCollector();
|
||||
assert queryParams.complete() == collector.scoreMode().isExhaustive();
|
||||
queryParams.getScoreModeOptional().ifPresent(scoreMode -> {
|
||||
assert scoreMode == collector.scoreMode();
|
||||
});
|
||||
|
||||
shard.search(queryParams.query(), collector);
|
||||
return collector;
|
||||
}))
|
||||
|
@ -46,7 +46,7 @@ public class UnsortedUnscoredSimpleMultiSearcher implements MultiSearcher {
|
||||
throw new UnsupportedOperationException("Sorted queries are not supported"
|
||||
+ " by SimpleUnsortedUnscoredLuceneMultiSearcher");
|
||||
}
|
||||
if (queryParams2.isScored() && queryParams2.limit() > 0) {
|
||||
if (queryParams2.needsScores() && queryParams2.limit() > 0) {
|
||||
throw new UnsupportedOperationException("Scored queries are not supported"
|
||||
+ " by SimpleUnsortedUnscoredLuceneMultiSearcher");
|
||||
}
|
||||
@ -97,7 +97,7 @@ public class UnsortedUnscoredSimpleMultiSearcher implements MultiSearcher {
|
||||
queryParams.pageLimits(),
|
||||
queryParams.minCompetitiveScore(),
|
||||
queryParams.sort(),
|
||||
queryParams.scoreMode()
|
||||
queryParams.complete()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ public class UnsortedUnscoredStreamingMultiSearcher implements MultiSearcher {
|
||||
return Mono.error(new UnsupportedOperationException("Sorted queries are not supported"
|
||||
+ " by UnsortedUnscoredContinuousLuceneMultiSearcher"));
|
||||
}
|
||||
if (queryParams2.isScored() && queryParams2.limit() > 0) {
|
||||
if (queryParams2.needsScores() && queryParams2.limit() > 0) {
|
||||
return Mono.error(new UnsupportedOperationException("Scored queries are not supported"
|
||||
+ " by UnsortedUnscoredContinuousLuceneMultiSearcher"));
|
||||
}
|
||||
@ -75,7 +75,13 @@ public class UnsortedUnscoredStreamingMultiSearcher implements MultiSearcher {
|
||||
UNSCORED_UNSORTED_EXECUTOR.schedule(() -> {
|
||||
try {
|
||||
var collector = cm.newCollector();
|
||||
assert queryParams.complete() == collector.scoreMode().isExhaustive();
|
||||
queryParams.getScoreModeOptional().ifPresent(scoreMode -> {
|
||||
assert scoreMode == collector.scoreMode();
|
||||
});
|
||||
|
||||
collector.setShardIndex(shardIndex);
|
||||
|
||||
shard.search(localQueryParams.query(), collector);
|
||||
} catch (Throwable e) {
|
||||
while (scoreDocsSink.tryEmitError(e) == EmitResult.FAIL_NON_SERIALIZED) {
|
||||
@ -111,7 +117,7 @@ public class UnsortedUnscoredStreamingMultiSearcher implements MultiSearcher {
|
||||
queryParams.pageLimits(),
|
||||
queryParams.minCompetitiveScore(),
|
||||
queryParams.sort(),
|
||||
queryParams.scoreMode()
|
||||
queryParams.complete()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,6 @@ import reactor.core.scheduler.Schedulers;
|
||||
|
||||
public class DbTestUtils {
|
||||
|
||||
|
||||
public static final String BIG_STRING = generateBigString();
|
||||
|
||||
private static String generateBigString() {
|
||||
|
@ -1,3 +1,3 @@
|
||||
package it.cavallium.dbengine;
|
||||
|
||||
record ExpectedQueryType(boolean shard, boolean sorted, boolean scored, boolean unlimited, boolean onlyCount) {}
|
||||
record ExpectedQueryType(boolean shard, boolean sorted, boolean complete, boolean onlyCount) {}
|
||||
|
@ -74,7 +74,7 @@ public class LocalTemporaryDbGenerator implements TemporaryDbGenerator {
|
||||
luceneHacks
|
||||
),
|
||||
conn.getLuceneIndex("testluceneindex16",
|
||||
1,
|
||||
3,
|
||||
IndicizerAnalyzers.of(TextFieldsAnalyzer.WordSimple),
|
||||
IndicizerSimilarities.of(TextFieldsSimilarity.Boolean),
|
||||
LUCENE_OPTS,
|
||||
|
@ -46,7 +46,7 @@ public class MemoryTemporaryDbGenerator implements TemporaryDbGenerator {
|
||||
luceneHacks
|
||||
),
|
||||
conn.getLuceneIndex("testluceneindex16",
|
||||
1,
|
||||
3,
|
||||
IndicizerAnalyzers.of(TextFieldsAnalyzer.WordSimple),
|
||||
IndicizerSimilarities.of(TextFieldsSimilarity.Boolean),
|
||||
LUCENE_OPTS,
|
||||
|
@ -72,7 +72,7 @@ public class TestLuceneSearches {
|
||||
private static LuceneIndex<String, String> multiIndex;
|
||||
private static LuceneIndex<String, String> localIndex;
|
||||
|
||||
private static Map<String, String> elements;
|
||||
private static final Map<String, String> ELEMENTS;
|
||||
static {
|
||||
var modifiableElements = new HashMap<String, String>();
|
||||
modifiableElements.put("test-key-1", "0123456789");
|
||||
@ -91,7 +91,7 @@ public class TestLuceneSearches {
|
||||
modifiableElements.put("test-key-14", "2999");
|
||||
modifiableElements.put("test-key-15", "3902");
|
||||
runVoid(Flux.range(1, 1000).doOnNext(i -> modifiableElements.put("test-key-" + (15 + i), "" + i)).then());
|
||||
elements = Collections.unmodifiableMap(modifiableElements);
|
||||
ELEMENTS = Collections.unmodifiableMap(modifiableElements);
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
@ -110,7 +110,7 @@ public class TestLuceneSearches {
|
||||
LuceneIndex<String, String> index = run(DbTestUtils.tempLuceneIndex(shards ? luceneSingle : luceneMulti));
|
||||
|
||||
Flux
|
||||
.fromIterable(elements.entrySet())
|
||||
.fromIterable(ELEMENTS.entrySet())
|
||||
.flatMap(entry -> index.updateDocument(entry.getKey(), entry.getValue()))
|
||||
.subscribeOn(Schedulers.boundedElastic())
|
||||
.blockLast();
|
||||
@ -129,11 +129,6 @@ public class TestLuceneSearches {
|
||||
}
|
||||
|
||||
private static final Flux<Boolean> multi = Flux.just(false, true);
|
||||
private static final Flux<LLScoreMode> scoreModes = Flux.just(LLScoreMode.NO_SCORES,
|
||||
LLScoreMode.TOP_SCORES,
|
||||
LLScoreMode.COMPLETE_NO_SCORES,
|
||||
LLScoreMode.COMPLETE
|
||||
);
|
||||
private static final Flux<MultiSort<SearchResultKey<String>>> multiSort = Flux.just(MultiSort.topScore(),
|
||||
//todo: fix random sort field
|
||||
//MultiSort.randomSortField(),
|
||||
@ -147,7 +142,6 @@ public class TestLuceneSearches {
|
||||
return Flux.push(sink -> {
|
||||
try {
|
||||
if (info.shard()) {
|
||||
sink.next(new AdaptiveMultiSearcher());
|
||||
if (info.onlyCount()) {
|
||||
sink.next(new UnsortedUnscoredSimpleMultiSearcher(new CountLocalSearcher()));
|
||||
} else {
|
||||
@ -155,18 +149,19 @@ public class TestLuceneSearches {
|
||||
if (!info.sorted()) {
|
||||
sink.next(new UnsortedScoredFullMultiSearcher());
|
||||
}
|
||||
if (!info.scored() && !info.sorted()) {
|
||||
if (!info.sorted()) {
|
||||
sink.next(new UnsortedUnscoredSimpleMultiSearcher(new PagedLocalSearcher()));
|
||||
sink.next(new UnsortedUnscoredStreamingMultiSearcher());
|
||||
}
|
||||
}
|
||||
sink.next(new AdaptiveMultiSearcher());
|
||||
} else {
|
||||
sink.next(new AdaptiveLocalSearcher());
|
||||
if (info.onlyCount()) {
|
||||
sink.next(new CountLocalSearcher());
|
||||
} else {
|
||||
sink.next(new PagedLocalSearcher());
|
||||
}
|
||||
sink.next(new AdaptiveLocalSearcher());
|
||||
}
|
||||
sink.complete();
|
||||
} catch (IOException e) {
|
||||
@ -176,35 +171,26 @@ public class TestLuceneSearches {
|
||||
}
|
||||
|
||||
public static Stream<Arguments> provideQueryArgumentsScoreMode() {
|
||||
return multi
|
||||
.concatMap(shard -> scoreModes.map(scoreMode -> Tuples.of(shard, scoreMode)))
|
||||
.map(tuple -> Arguments.of(tuple.toArray()))
|
||||
.toStream();
|
||||
}
|
||||
|
||||
public static Stream<Arguments> provideQueryArgumentsSort() {
|
||||
return multi
|
||||
.concatMap(shard -> multiSort.map(multiSort -> Tuples.of(shard, multiSort)))
|
||||
.map(tuple -> Arguments.of(tuple.toArray()))
|
||||
.toStream();
|
||||
return multi.map(tuple -> Arguments.of(multi)).toStream();
|
||||
}
|
||||
|
||||
public static Stream<Arguments> provideQueryArgumentsScoreModeAndSort() {
|
||||
return multi
|
||||
.concatMap(shard -> scoreModes.map(scoreMode -> Tuples.of(shard, scoreMode)))
|
||||
.concatMap(tuple -> multiSort.map(multiSort -> Tuples.of(tuple.getT1(), tuple.getT2(), multiSort)))
|
||||
.concatMap(multi -> multiSort.map(multiSort -> Tuples.of(multi, multiSort)))
|
||||
.map(tuple -> Arguments.of(tuple.toArray()))
|
||||
.toStream();
|
||||
}
|
||||
|
||||
private static void runSearchers(ExpectedQueryType expectedQueryType, FailableConsumer<LocalSearcher, Throwable> consumer) {
|
||||
Assertions.assertDoesNotThrow(() -> {
|
||||
var searchers = run(getSearchers(expectedQueryType).collectList());
|
||||
for (LocalSearcher searcher : searchers) {
|
||||
log.info("Using searcher \"{}\"", searcher.getName());
|
||||
var searchers = run(getSearchers(expectedQueryType).collectList());
|
||||
for (LocalSearcher searcher : searchers) {
|
||||
log.info("Using searcher \"{}\"", searcher.getName());
|
||||
try {
|
||||
consumer.accept(searcher);
|
||||
} catch (Throwable e) {
|
||||
Assertions.fail(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
@ -248,28 +234,25 @@ public class TestLuceneSearches {
|
||||
|
||||
private boolean supportsPreciseHitsCount(LocalSearcher searcher,
|
||||
ClientQueryParams<SearchResultKey<String>> query) {
|
||||
var sorted = query.isSorted();
|
||||
if (searcher instanceof UnsortedUnscoredStreamingMultiSearcher) {
|
||||
return false;
|
||||
} else if (!sorted) {
|
||||
return !(searcher instanceof AdaptiveMultiSearcher) && !(searcher instanceof AdaptiveLocalSearcher);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
var scored = isScored(query.scoreMode(), Objects.requireNonNullElse(query.sort(), MultiSort.noSort()));
|
||||
var sorted = isSorted(Objects.requireNonNullElse(query.sort(), MultiSort.noSort()));
|
||||
if (!sorted && !scored) {
|
||||
if (searcher instanceof AdaptiveMultiSearcher || searcher instanceof AdaptiveLocalSearcher) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideQueryArgumentsScoreModeAndSort")
|
||||
public void testSearchNoDocs(boolean shards, LLScoreMode scoreMode, MultiSort<SearchResultKey<String>> multiSort) {
|
||||
runSearchers(new ExpectedQueryType(shards, isSorted(multiSort), isScored(scoreMode, multiSort), true, false), searcher -> {
|
||||
public void testSearchNoDocs(boolean shards, MultiSort<SearchResultKey<String>> multiSort) {
|
||||
runSearchers(new ExpectedQueryType(shards, multiSort.isSorted(), true, false), searcher -> {
|
||||
var luceneIndex = getLuceneIndex(shards, searcher);
|
||||
ClientQueryParamsBuilder<SearchResultKey<String>> queryBuilder = ClientQueryParams.builder();
|
||||
queryBuilder.query(new MatchNoDocsQuery());
|
||||
queryBuilder.snapshot(null);
|
||||
queryBuilder.scoreMode(scoreMode);
|
||||
queryBuilder.complete(true);
|
||||
queryBuilder.sort(multiSort);
|
||||
var query = queryBuilder.build();
|
||||
try (var results = run(luceneIndex.search(query)).receive()) {
|
||||
@ -284,22 +267,22 @@ public class TestLuceneSearches {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideQueryArgumentsScoreModeAndSort")
|
||||
public void testSearchAllDocs(boolean shards, LLScoreMode scoreMode, MultiSort<SearchResultKey<String>> multiSort) {
|
||||
var sorted = isSorted(multiSort);
|
||||
runSearchers(new ExpectedQueryType(shards, sorted, isScored(scoreMode, multiSort), true, false), (LocalSearcher searcher) -> {
|
||||
public void testSearchAllDocs(boolean shards, MultiSort<SearchResultKey<String>> multiSort) {
|
||||
var sorted = multiSort.isSorted();
|
||||
runSearchers(new ExpectedQueryType(shards, sorted, true, false), (LocalSearcher searcher) -> {
|
||||
var luceneIndex = getLuceneIndex(shards, searcher);
|
||||
ClientQueryParamsBuilder<SearchResultKey<String>> queryBuilder = ClientQueryParams.builder();
|
||||
queryBuilder.query(new MatchAllDocsQuery());
|
||||
queryBuilder.snapshot(null);
|
||||
queryBuilder.scoreMode(scoreMode);
|
||||
queryBuilder.complete(true);
|
||||
queryBuilder.sort(multiSort);
|
||||
var query = queryBuilder.build();
|
||||
try (var results = run(luceneIndex.search(query)).receive()) {
|
||||
var hits = results.totalHitsCount();
|
||||
assertHitsIfPossible(0, hits);
|
||||
assertHitsIfPossible(ELEMENTS.size(), hits);
|
||||
|
||||
var keys = getResults(results);
|
||||
assertResults(elements.keySet().stream().toList(), keys, false);
|
||||
assertResults(ELEMENTS.keySet().stream().toList(), keys, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -329,19 +312,6 @@ public class TestLuceneSearches {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSorted(MultiSort<SearchResultKey<String>> multiSort) {
|
||||
return !(multiSort.getQuerySort() instanceof NoSort);
|
||||
}
|
||||
|
||||
private boolean isScored(LLScoreMode scoreMode, MultiSort<SearchResultKey<String>> multiSort) {
|
||||
var needsScores = LLUtils.toScoreMode(scoreMode).needsScores();
|
||||
var sort =QueryParser.toSort(multiSort.getQuerySort());
|
||||
if (sort != null) {
|
||||
needsScores |= sort.needsScores();
|
||||
}
|
||||
return needsScores;
|
||||
}
|
||||
|
||||
private List<Scored> getResults(SearchResultKeys<String> results) {
|
||||
return run(results
|
||||
.results()
|
||||
|
Loading…
Reference in New Issue
Block a user