CavalliumDBEngine/src/main/java/it/cavallium/dbengine/client/LuceneIndex.java

235 lines
7.8 KiB
Java
Raw Normal View History

2021-02-03 20:13:17 +01:00
package it.cavallium.dbengine.client;
import it.cavallium.dbengine.database.LLLuceneIndex;
import it.cavallium.dbengine.database.LLScoreMode;
import it.cavallium.dbengine.database.LLSearchResult;
import it.cavallium.dbengine.database.LLSnapshot;
import it.cavallium.dbengine.database.LLSnapshottable;
import it.cavallium.dbengine.database.LLSort;
import it.cavallium.dbengine.database.LLTerm;
import it.cavallium.dbengine.lucene.LuceneUtils;
2021-02-03 20:13:17 +01:00
import it.cavallium.dbengine.database.collections.Joiner.ValueGetter;
import it.cavallium.dbengine.lucene.serializer.Query;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.jetbrains.annotations.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.function.Tuple2;
public class LuceneIndex<T, U> implements LLSnapshottable {
private final LLLuceneIndex luceneIndex;
private final Indicizer<T,U> indicizer;
public LuceneIndex(LLLuceneIndex luceneIndex, Indicizer<T, U> indicizer) {
this.luceneIndex = luceneIndex;
this.indicizer = indicizer;
}
private LLSnapshot resolveSnapshot(CompositeSnapshot snapshot) {
if (snapshot == null) {
return null;
} else {
return snapshot.getSnapshot(luceneIndex);
}
}
public Mono<Void> addDocument(T key, U value) {
return indicizer
.toDocument(key, value)
.flatMap(doc -> luceneIndex.addDocument(indicizer.toIndex(key), doc));
}
public Mono<Void> addDocuments(Flux<Entry<T, U>> entries) {
return luceneIndex
.addDocuments(entries
.flatMap(entry -> indicizer
.toDocument(entry.getKey(), entry.getValue())
.map(doc -> Map.entry(indicizer.toIndex(entry.getKey()), doc)))
.groupBy(Entry::getKey, Entry::getValue)
);
}
public Mono<Void> deleteDocument(T key) {
LLTerm id = indicizer.toIndex(key);
return luceneIndex.deleteDocument(id);
}
public Mono<Void> updateDocument(T key, U value) {
return indicizer
.toDocument(key, value)
.flatMap(doc -> luceneIndex.updateDocument(indicizer.toIndex(key), doc));
}
public Mono<Void> updateDocuments(Flux<Entry<T, U>> entries) {
return luceneIndex
.updateDocuments(entries
.flatMap(entry -> indicizer
.toDocument(entry.getKey(), entry.getValue())
.map(doc -> Map.entry(indicizer.toIndex(entry.getKey()), doc)))
.groupBy(Entry::getKey, Entry::getValue)
);
}
public Mono<Void> deleteAll() {
return luceneIndex.deleteAll();
}
private SearchResultKeys<T> transformLuceneResult(LLSearchResult llSearchResult,
@Nullable MultiSort<SearchResultKey<T>> sort,
2021-02-14 03:25:15 +01:00
LLScoreMode scoreMode,
2021-02-22 01:54:25 +01:00
@Nullable Long limit) {
2021-02-03 20:13:17 +01:00
var mappedKeys = llSearchResult
.results()
.map(flux -> flux.map(item -> new SearchResultKey<>(indicizer.getKey(item.getKey()), item.getScore())));
2021-02-14 03:25:15 +01:00
if (scoreMode != LLScoreMode.COMPLETE_NO_SCORES && sort == null) {
sort = MultiSort.topScore();
}
2021-02-03 20:13:17 +01:00
var sortedKeys = LuceneUtils.mergeStream(mappedKeys, sort, limit);
return new SearchResultKeys<>(llSearchResult.totalHitsCount(), sortedKeys);
}
private SearchResult<T, U> transformLuceneResultWithValues(LLSearchResult llSearchResult,
@Nullable MultiSort<SearchResultItem<T, U>> sort,
2021-02-14 03:25:15 +01:00
LLScoreMode scoreMode,
@Nullable Long limit,
2021-02-03 20:13:17 +01:00
ValueGetter<T, U> valueGetter) {
var mappedKeys = llSearchResult
.results()
.map(flux -> flux.flatMapSequential(item -> {
2021-02-03 20:13:17 +01:00
var key = indicizer.getKey(item.getKey());
return valueGetter.get(key).map(value -> new SearchResultItem<>(key, value, item.getScore()));
}));
2021-02-14 03:25:15 +01:00
if (scoreMode != LLScoreMode.COMPLETE_NO_SCORES && sort == null) {
sort = MultiSort.topScoreWithValues();
}
2021-02-03 20:13:17 +01:00
var sortedKeys = LuceneUtils.mergeStream(mappedKeys, sort, limit);
return new SearchResult<>(llSearchResult.totalHitsCount(), sortedKeys);
}
/**
*
* @param limit the limit is valid for each lucene instance.
* If you have 15 instances, the number of elements returned
* can be at most <code>limit * 15</code>
* @return the collection has one or more flux
*/
public Mono<SearchResultKeys<T>> moreLikeThis(@Nullable CompositeSnapshot snapshot,
2021-02-06 15:53:10 +01:00
T key,
2021-02-03 20:13:17 +01:00
U mltDocumentValue,
2021-02-22 01:54:25 +01:00
long limit,
2021-02-14 13:46:11 +01:00
@Nullable Float minCompetitiveScore) {
2021-02-06 15:53:10 +01:00
Flux<Tuple2<String, Set<String>>> mltDocumentFields
= indicizer.getMoreLikeThisDocumentFields(key, mltDocumentValue);
2021-02-03 20:13:17 +01:00
return luceneIndex
2021-02-14 13:46:11 +01:00
.moreLikeThis(resolveSnapshot(snapshot), mltDocumentFields, limit,
minCompetitiveScore, indicizer.getKeyFieldName())
2021-02-14 03:25:15 +01:00
.map(llSearchResult -> this.transformLuceneResult(llSearchResult, null, LLScoreMode.TOP_SCORES, limit));
2021-02-03 20:13:17 +01:00
}
/**
*
* @param limit the limit is valid for each lucene instance.
* If you have 15 instances, the number of elements returned
* can be at most <code>limit * 15</code>
* @return the collection has one or more flux
*/
public Mono<SearchResult<T, U>> moreLikeThisWithValues(@Nullable CompositeSnapshot snapshot,
2021-02-06 15:53:10 +01:00
T key,
2021-02-03 20:13:17 +01:00
U mltDocumentValue,
2021-02-22 01:54:25 +01:00
long limit,
2021-02-14 13:46:11 +01:00
@Nullable Float minCompetitiveScore,
2021-02-03 20:13:17 +01:00
ValueGetter<T, U> valueGetter) {
2021-02-06 15:53:10 +01:00
Flux<Tuple2<String, Set<String>>> mltDocumentFields
= indicizer.getMoreLikeThisDocumentFields(key, mltDocumentValue);
2021-02-03 20:13:17 +01:00
return luceneIndex
2021-02-14 13:46:11 +01:00
.moreLikeThis(resolveSnapshot(snapshot), mltDocumentFields, limit,
minCompetitiveScore, indicizer.getKeyFieldName())
2021-02-03 20:13:17 +01:00
.map(llSearchResult ->
2021-02-14 03:25:15 +01:00
this.transformLuceneResultWithValues(llSearchResult, null, LLScoreMode.TOP_SCORES, limit, valueGetter));
2021-02-03 20:13:17 +01:00
}
/**
*
* @param limit the limit is valid for each lucene instance.
* If you have 15 instances, the number of elements returned
* can be at most <code>limit * 15</code>
* @return the collection has one or more flux
*/
public Mono<SearchResultKeys<T>> search(@Nullable CompositeSnapshot snapshot,
Query query,
2021-02-22 01:54:25 +01:00
long limit,
2021-02-03 20:13:17 +01:00
@Nullable MultiSort<SearchResultKey<T>> sort,
2021-02-14 13:46:11 +01:00
LLScoreMode scoreMode,
@Nullable Float minCompetitiveScore) {
2021-02-03 20:13:17 +01:00
LLSort querySort = sort != null ? sort.getQuerySort() : null;
return luceneIndex
2021-02-14 13:46:11 +01:00
.search(resolveSnapshot(snapshot), query, limit, querySort, scoreMode, minCompetitiveScore,
indicizer.getKeyFieldName())
2021-02-14 03:25:15 +01:00
.map(llSearchResult -> this.transformLuceneResult(llSearchResult, sort, scoreMode, limit));
2021-02-03 20:13:17 +01:00
}
/**
*
* @param limit the limit is valid for each lucene instance.
* If you have 15 instances, the number of elements returned
* can be at most <code>limit * 15</code>
* @return the collection has one or more flux
*/
public Mono<SearchResult<T, U>> searchWithValues(@Nullable CompositeSnapshot snapshot,
Query query,
long limit,
2021-02-03 20:13:17 +01:00
@Nullable MultiSort<SearchResultItem<T, U>> sort,
LLScoreMode scoreMode,
2021-02-14 13:46:11 +01:00
@Nullable Float minCompetitiveScore,
2021-02-03 20:13:17 +01:00
ValueGetter<T, U> valueGetter) {
LLSort querySort = sort != null ? sort.getQuerySort() : null;
return luceneIndex
2021-02-14 13:46:11 +01:00
.search(resolveSnapshot(snapshot), query, limit, querySort, scoreMode, minCompetitiveScore,
indicizer.getKeyFieldName())
2021-02-14 03:25:15 +01:00
.map(llSearchResult -> this.transformLuceneResultWithValues(llSearchResult, sort, scoreMode, limit, valueGetter));
2021-02-03 20:13:17 +01:00
}
public Mono<Long> count(@Nullable CompositeSnapshot snapshot, Query query) {
2021-02-17 15:03:51 +01:00
return this.search(snapshot, query, 0, null, LLScoreMode.COMPLETE_NO_SCORES, null)
2021-02-03 20:13:17 +01:00
.flatMap(SearchResultKeys::totalHitsCount)
.single();
}
public boolean isLowMemoryMode() {
return luceneIndex.isLowMemoryMode();
}
public Mono<Void> close() {
return luceneIndex.close();
}
/**
* Flush writes to disk
*/
public Mono<Void> flush() {
return luceneIndex.flush();
}
/**
* Refresh index searcher
*/
public Mono<Void> refresh() {
return luceneIndex.refresh();
}
@Override
public Mono<LLSnapshot> takeSnapshot() {
return luceneIndex.takeSnapshot();
}
@Override
public Mono<Void> releaseSnapshot(LLSnapshot snapshot) {
return luceneIndex.releaseSnapshot(snapshot);
}
}