This is the codeAbility Sharing Platform! Learn more about the codeAbility Sharing Platform.

Skip to content
Snippets Groups Projects

Resolve "Relevance Ranking in Metadata"

Merged Philipp Gritsch requested to merge 439-relevance-ranking-in-metadata into development
Files
6
@@ -7,8 +7,9 @@ import at.ac.uibk.gitsearch.repository.jpa.StatisticsRepository;
import at.ac.uibk.gitsearch.service.dto.AutoCompleteEntry;
import at.ac.uibk.gitsearch.service.dto.StatisticsDTO;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldSort;
import co.elastic.clients.elasticsearch._types.ScriptSortType;
import co.elastic.clients.elasticsearch._types.SortOptions;
import co.elastic.clients.elasticsearch._types.SortOptionsBuilders;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.ExistsQuery;
@@ -59,10 +60,12 @@ import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import javax.annotation.PostConstruct;
import javax.ws.rs.NotFoundException;
import liquibase.repackaged.org.apache.commons.text.StringSubstitutor;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codeability.sharing.plugins.api.search.SearchInputDTO;
import org.codeability.sharing.plugins.api.search.SearchOrdering;
import org.codeability.sharing.plugins.api.search.SearchResultDTO;
import org.codeability.sharing.plugins.api.search.SearchResultsDTO;
import org.codeability.sharing.plugins.api.search.UserProvidedMetadataDTO.Person;
@@ -535,8 +538,6 @@ public class MetaDataRepository {
* parameters.
*
* @param searchInputDTO the query parameters.
* @param pageSize the size of the page (i.e. the maximum of returned
* hits).
* @param user the user that queries.
* @return the search hits.
* @throws IOException when search index is not available.
@@ -572,7 +573,7 @@ public class MetaDataRepository {
search
.index(SearchRepositoryConstants.INDEX_METADATA)
.query(q -> q.bool(query))
.sort(getDefaultSortStrategy())
.sort(getSortStrategy(searchInputDTO.getOrdering()))
.from(from)
.size(pageSize),
SearchResultDTO.class
@@ -592,16 +593,46 @@ public class MetaDataRepository {
}
}
private List<SortOptions> getDefaultSortStrategy() {
return List.of(
getSortOptionForFieldAndOrder(SearchRepositoryConstants.SEARCHSTATISTICS_BADGEREWARDED, SortOrder.Desc),
getSortOptionForFieldAndOrder(SearchRepositoryConstants.SEARCHSTATISTICS_DOWNLOADS, SortOrder.Desc),
getSortOptionForFieldAndOrder(SearchRepositoryConstants.SEARCHSTATISTICS_VIEWS, SortOrder.Desc)
private List<SortOptions> getSortStrategy(SearchOrdering searchOrdering) {
String sortingScriptTemplate =
"double boost = 0;" +
"if (doc.containsKey('${badgeRewarded}') && doc['${badgeRewarded}'].size() > 0) {" +
" boost = boost + (doc['${badgeRewarded}'].value ? 1.0 : 0.0) * params.factorBadge;" +
"}" +
"if (doc.containsKey('${downloads}') && doc['${downloads}'].size() > 0) {" +
" boost = boost + doc['${downloads}'].value * params.factorDownloads;" +
"}" +
"if (doc.containsKey('${views}') && doc['${views}'].size() > 0) {" +
" boost = boost + doc['${views}'].value * params.factorViews;" +
"}" +
"return boost;";
Map<String, String> templateValueMapping = Map.of(
"badgeRewarded",
SearchRepositoryConstants.SEARCHSTATISTICS_BADGEREWARDED,
"downloads",
SearchRepositoryConstants.SEARCHSTATISTICS_DOWNLOADS,
"views",
SearchRepositoryConstants.SEARCHSTATISTICS_VIEWS
);
var scriptSort = SortOptionsBuilders.script(b ->
b
.type(ScriptSortType.Number)
.order(SortOrder.Desc)
.script(sb ->
sb.inline(isb ->
isb
.lang("painless")
.source(StringSubstitutor.replace(sortingScriptTemplate, templateValueMapping))
.params("factorBadge", JsonData.of(searchOrdering.getFactorBadge()))
.params("factorDownloads", JsonData.of(searchOrdering.getFactorDownloads()))
.params("factorViews", JsonData.of(searchOrdering.getFactorViews()))
)
)
);
}
private SortOptions getSortOptionForFieldAndOrder(String field, SortOrder order) {
return SortOptions.of(sb -> sb.field(FieldSort.of(fb -> fb.field(field).order(order))));
return List.of(SortOptionsBuilders.score(s -> s.order(SortOrder.Desc)), scriptSort);
}
/**
@@ -795,12 +826,14 @@ public class MetaDataRepository {
*/
private void addAuthorizationQueryWithJavaApi(Optional<User> user, BoolQuery.Builder queryBuilder) {
// Authorization restrictions
// the boost value of 0 tells elastic to exclude these restrictions from the scoring process
final TermQuery.Builder simplePublicQuery = new TermQuery.Builder()
.value("public")
.field(SearchRepositoryConstants.PROJECT_VISIBILITY)
.boost(0.0f);
final ExistsQuery.Builder publicVisibilityQuery = new ExistsQuery.Builder()
.field(SearchRepositoryConstants.METADATA_PUBLICVISIBILITY);
.field(SearchRepositoryConstants.METADATA_PUBLICVISIBILITY)
.boost(0.0f);
final BoolQuery.Builder publicQuery = new BoolQuery.Builder()
.should(q -> q.term(simplePublicQuery.build()))
.should(q -> q.exists(publicVisibilityQuery.build()));