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

285 lines
8.9 KiB
Java
Raw Normal View History

2021-04-03 19:09:06 +02:00
package it.cavallium.dbengine.client;
import it.cavallium.dbengine.client.query.ClientQueryParams;
import it.cavallium.dbengine.client.query.current.data.Query;
import it.cavallium.dbengine.client.query.current.data.QueryParams;
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.LLTerm;
import it.cavallium.dbengine.database.collections.Joiner.ValueGetter;
import it.cavallium.dbengine.lucene.LuceneUtils;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
2021-06-07 16:21:12 +02:00
import org.jetbrains.annotations.NotNull;
2021-04-03 19:09:06 +02:00
import org.jetbrains.annotations.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.function.Tuple2;
public class LuceneIndexImpl<T, U> implements LuceneIndex<T, U> {
private final LLLuceneIndex luceneIndex;
private final Indicizer<T,U> indicizer;
public LuceneIndexImpl(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);
}
}
@Override
public Mono<Void> addDocument(T key, U value) {
return indicizer
.toDocument(key, value)
.flatMap(doc -> luceneIndex.addDocument(indicizer.toIndex(key), doc));
}
@Override
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)))
);
}
@Override
public Mono<Void> deleteDocument(T key) {
LLTerm id = indicizer.toIndex(key);
return luceneIndex.deleteDocument(id);
}
@Override
2021-06-07 16:21:12 +02:00
public Mono<Void> updateDocument(T key, @NotNull U value) {
2021-04-03 19:09:06 +02:00
return indicizer
.toDocument(key, value)
.flatMap(doc -> luceneIndex.updateDocument(indicizer.toIndex(key), doc));
}
@Override
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)))
.collectMap(Entry::getKey, Entry::getValue)
2021-04-03 19:09:06 +02:00
);
}
@Override
public Mono<Void> deleteAll() {
return luceneIndex.deleteAll();
}
private static QueryParams fixOffset(LLLuceneIndex luceneIndex, QueryParams queryParams) {
if (luceneIndex.supportsOffset()) {
return queryParams;
} else {
2021-07-05 15:43:19 +02:00
return queryParams.setOffset(0).setLimit(queryParams.limit() + queryParams.offset());
2021-04-03 19:09:06 +02:00
}
}
private static long fixTransformOffset(LLLuceneIndex luceneIndex, long offset) {
if (luceneIndex.supportsOffset()) {
return 0;
} else {
return offset;
}
}
private Mono<SearchResultKeys<T>> transformLuceneResult(LLSearchResult llSearchResult,
@Nullable MultiSort<SearchResultKey<T>, ?> sort,
2021-04-03 19:09:06 +02:00
LLScoreMode scoreMode,
long offset,
@Nullable Long limit) {
Flux<SearchResultKeys<T>> mappedKeys = llSearchResult
2021-05-21 00:19:40 +02:00
.results()
2021-04-03 19:09:06 +02:00
.map(flux -> new SearchResultKeys<>(flux
2021-05-21 00:19:40 +02:00
.results()
.map(signal -> new SearchResultKey<>(signal.key().map(indicizer::getKey), signal.score())),
2021-05-21 00:19:40 +02:00
flux.totalHitsCount()
2021-04-03 19:09:06 +02:00
));
MultiSort<SearchResultKey<T>, ?> finalSort;
2021-04-03 19:09:06 +02:00
if (scoreMode != LLScoreMode.COMPLETE_NO_SCORES && sort == null) {
finalSort = MultiSort.topScore();
} else {
finalSort = sort;
}
return LuceneUtils.mergeSignalStreamKeys(mappedKeys, finalSort, offset, limit);
2021-04-03 19:09:06 +02:00
}
private <V> Mono<SearchResult<T, U>> transformLuceneResultWithValues(LLSearchResult llSearchResult,
@Nullable MultiSort<SearchResultItem<T, U>, V> sort,
2021-04-03 19:09:06 +02:00
LLScoreMode scoreMode,
long offset,
@Nullable Long limit,
ValueGetter<T, U> valueGetter) {
Flux<SearchResult<T, U>> mappedKeys = llSearchResult
2021-05-21 00:19:40 +02:00
.results()
.map(flux -> new SearchResult<>(flux
.results()
.map(signal -> {
var key = signal.key().map(indicizer::getKey);
return new SearchResultItem<>(key, key.flatMap(valueGetter::get), signal.score());
}), flux.totalHitsCount()));
MultiSort<SearchResultItem<T, U>, ?> finalSort;
2021-04-03 19:09:06 +02:00
if (scoreMode != LLScoreMode.COMPLETE_NO_SCORES && sort == null) {
finalSort = MultiSort.topScoreWithValues();
} else {
finalSort = sort;
}
return LuceneUtils.mergeSignalStreamItems(mappedKeys, finalSort, offset, limit);
2021-04-03 19:09:06 +02:00
}
/**
*
* @param queryParams 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
*/
@Override
public <V> Mono<SearchResultKeys<T>> moreLikeThis(ClientQueryParams<SearchResultKey<T>, V> queryParams,
2021-04-03 19:09:06 +02:00
T key,
U mltDocumentValue) {
Flux<Tuple2<String, Set<String>>> mltDocumentFields
= indicizer.getMoreLikeThisDocumentFields(key, mltDocumentValue);
return luceneIndex
2021-05-21 00:19:40 +02:00
.moreLikeThis(resolveSnapshot(queryParams.snapshot()), fixOffset(luceneIndex, queryParams.toQueryParams()), indicizer.getKeyFieldName(), mltDocumentFields)
2021-04-03 19:09:06 +02:00
.flatMap(llSearchResult -> this.transformLuceneResult(llSearchResult,
2021-05-21 00:19:40 +02:00
queryParams.sort(),
queryParams.scoreMode(),
fixTransformOffset(luceneIndex, queryParams.offset()),
queryParams.limit()
2021-04-03 19:09:06 +02:00
));
}
/**
*
* @param queryParams 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
*/
@Override
public <V> Mono<SearchResult<T, U>> moreLikeThisWithValues(ClientQueryParams<SearchResultItem<T, U>, V> queryParams,
2021-04-03 19:09:06 +02:00
T key,
U mltDocumentValue,
ValueGetter<T, U> valueGetter) {
Flux<Tuple2<String, Set<String>>> mltDocumentFields
= indicizer.getMoreLikeThisDocumentFields(key, mltDocumentValue);
return luceneIndex
2021-05-21 00:19:40 +02:00
.moreLikeThis(resolveSnapshot(queryParams.snapshot()),
2021-04-03 19:09:06 +02:00
fixOffset(luceneIndex, queryParams.toQueryParams()),
indicizer.getKeyFieldName(),
mltDocumentFields
)
.flatMap(llSearchResult -> this.transformLuceneResultWithValues(llSearchResult,
2021-05-21 00:19:40 +02:00
queryParams.sort(),
queryParams.scoreMode(),
fixTransformOffset(luceneIndex, queryParams.offset()),
queryParams.limit(),
2021-04-03 19:09:06 +02:00
valueGetter
));
}
/**
*
* @param queryParams 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
*/
@Override
public <V> Mono<SearchResultKeys<T>> search(ClientQueryParams<SearchResultKey<T>, V> queryParams) {
2021-04-03 19:09:06 +02:00
return luceneIndex
2021-05-21 00:19:40 +02:00
.search(resolveSnapshot(queryParams.snapshot()),
2021-04-03 19:09:06 +02:00
fixOffset(luceneIndex, queryParams.toQueryParams()),
indicizer.getKeyFieldName()
)
.flatMap(llSearchResult -> this.transformLuceneResult(llSearchResult,
2021-05-21 00:19:40 +02:00
queryParams.sort(),
queryParams.scoreMode(),
fixTransformOffset(luceneIndex, queryParams.offset()),
queryParams.limit()
2021-04-03 19:09:06 +02:00
));
}
/**
*
* @param queryParams 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
*/
@Override
public <V> Mono<SearchResult<T, U>> searchWithValues(ClientQueryParams<SearchResultItem<T, U>, V> queryParams,
2021-04-03 19:09:06 +02:00
ValueGetter<T, U> valueGetter) {
return luceneIndex
2021-05-21 00:19:40 +02:00
.search(resolveSnapshot(queryParams.snapshot()), fixOffset(luceneIndex, queryParams.toQueryParams()), indicizer.getKeyFieldName())
2021-04-03 19:09:06 +02:00
.flatMap(llSearchResult -> this.transformLuceneResultWithValues(llSearchResult,
2021-05-21 00:19:40 +02:00
queryParams.sort(),
queryParams.scoreMode(),
fixTransformOffset(luceneIndex, queryParams.offset()),
queryParams.limit(),
2021-04-03 19:09:06 +02:00
valueGetter
));
}
@Override
public Mono<Long> count(@Nullable CompositeSnapshot snapshot, Query query) {
return this.search(ClientQueryParams.<SearchResultKey<T>, Object>builder().snapshot(snapshot).query(query).limit(0).build())
2021-05-21 00:19:40 +02:00
.map(SearchResultKeys::totalHitsCount);
2021-04-03 19:09:06 +02:00
}
@Override
public boolean isLowMemoryMode() {
return luceneIndex.isLowMemoryMode();
}
@Override
public Mono<Void> close() {
return luceneIndex.close();
}
/**
* Flush writes to disk
*/
@Override
public Mono<Void> flush() {
return luceneIndex.flush();
}
/**
* Refresh index searcher
*/
@Override
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);
}
}