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
8
@@ -7,6 +7,10 @@ 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.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;
import co.elastic.clients.elasticsearch._types.query_dsl.MatchPhrasePrefixQuery;
@@ -56,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;
@@ -532,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.
@@ -565,7 +569,13 @@ public class MetaDataRepository {
final BoolQuery query = queryBuilder.build();
// LOGGER.info("ElasticSearch Query using Java Client API:\n{}", query)
co.elastic.clients.elasticsearch.core.SearchResponse<SearchResultDTO> searchResponse = elasticsearchAPIClient.search(
search -> search.index(SearchRepositoryConstants.INDEX_METADATA).query(q -> q.bool(query)).from(from).size(pageSize),
search ->
search
.index(SearchRepositoryConstants.INDEX_METADATA)
.query(q -> q.bool(query))
.sort(getSortStrategy(searchInputDTO.getOrdering()))
.from(from)
.size(pageSize),
SearchResultDTO.class
);
@@ -583,6 +593,48 @@ public class MetaDataRepository {
}
}
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()))
)
)
);
return List.of(SortOptionsBuilders.score(s -> s.order(SortOrder.Desc)), scriptSort);
}
/**
* creates the query (builder) for the searchInput and the user authorization
*
@@ -774,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()));