Skip to content
Snippets Groups Projects
Commit 9c3b7d69 authored by vkovtun's avatar vkovtun
Browse files

SSDM-9369 Added results merging, so that multiple matches have higher rank and...

SSDM-9369 Added results merging, so that multiple matches have higher rank and the matches and their spans in the same row are merged.
parent ca529f29
No related branches found
No related tags found
No related merge requests found
......@@ -126,9 +126,11 @@ public class SearchGloballyOperationExecutor
allResultMaps.addAll(materialResultMaps);
}
final List<Map<String, Object>> sortedAndPagedResultMaps = sortAndPage(allResultMaps, fetchOptions);
final Collection<MatchingEntity> pagedMatchingEntities = globalSearchManager.map(sortedAndPagedResultMaps,
final List<Map<String, Object>> sortedResultMaps = sort(allResultMaps, fetchOptions.getSortBy());
final Collection<MatchingEntity> matchingEntities = globalSearchManager.map(sortedResultMaps,
fetchOptions.hasMatch());
final List<MatchingEntity> pagedMatchingEntities = page(new ArrayList<>(matchingEntities), fetchOptions);
// TODO: doTranslate() should only filter nested objects of the results (parents, children, components...).
final Map<MatchingEntity, GlobalSearchObject> pagedResultV3DTOs = doTranslate(translationContext, pagedMatchingEntities, fetchOptions);
......@@ -177,17 +179,20 @@ public class SearchGloballyOperationExecutor
return objectKinds.isEmpty() ? EnumSet.allOf(GlobalSearchObjectKind.class) : objectKinds;
}
protected List<Map<String, Object>> sortAndPage(final Set<Map<String, Object>> results, final FetchOptions<GlobalSearchObject> fo)
protected List<Map<String, Object>> sort(final Set<Map<String, Object>> results,
final SortOptions<GlobalSearchObject> sortOptions)
{
final SortOptions<GlobalSearchObject> sortOptions = fo.getSortBy();
final List<Map<String, Object>> orderedIDs = (sortOptions != null)
return (sortOptions != null)
? globalSearchManager.sortRecords(results, sortOptions)
: new ArrayList<>(results);
}
protected List<MatchingEntity> page(final List<MatchingEntity> results, final FetchOptions<GlobalSearchObject> fo)
{
final Integer fromRecord = fo.getFrom();
final Integer recordsCount = fo.getCount();
final boolean hasPaging = fromRecord != null && recordsCount != null;
return hasPaging ? orderedIDs.subList(fromRecord, Math.min(fromRecord + recordsCount, orderedIDs.size())) : orderedIDs;
return hasPaging ? results.subList(fromRecord, Math.min(fromRecord + recordsCount, results.size())) : results;
}
@Override
......
......@@ -13,6 +13,7 @@ import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import static ch.ethz.sis.openbis.generic.asapi.v3.dto.global.fetchoptions.GlobalSearchObjectSortOptions.*;
......@@ -61,8 +62,8 @@ public class GlobalSearchManager implements IGlobalSearchManager
// If we have results, we use them
// If we don't have results and criteria are not empty, there are no results.
final Set<Map<String, Object>> resultBeforeFiltering =
containsValues(mainCriteriaIntermediateResults) ? mainCriteriaIntermediateResults : Collections.emptySet();
final Set<Map<String, Object>> resultBeforeFiltering = containsValues(mainCriteriaIntermediateResults)
? mainCriteriaIntermediateResults : Collections.emptySet();
return filterResultsByUserRights(authorisationInformation, resultBeforeFiltering, tableMapper);
}
......@@ -202,7 +203,37 @@ public class GlobalSearchManager implements IGlobalSearchManager
matchingEntity.setMatches(matches);
return matchingEntity;
}).collect(Collectors.toList());
}).collect(Collectors.toMap(MatchingEntity::getId, Function.identity(),
(existingMatchingEntity, newMatchingEntity) ->
{
existingMatchingEntity.setScore(existingMatchingEntity.getScore() + newMatchingEntity.getScore());
if (withMatches)
{
final Collection<PropertyMatch> existingMatches = existingMatchingEntity.getMatches();
final Collection<PropertyMatch> newMatches = newMatchingEntity.getMatches();
final Collection<PropertyMatch> mergedMatches = mergeMatches(existingMatches, newMatches);
existingMatchingEntity.setMatches(new ArrayList<>(mergedMatches));
}
return existingMatchingEntity;
},
LinkedHashMap::new
)).values();
}
private Collection<PropertyMatch> mergeMatches(final Collection<PropertyMatch> existingMatches,
final Collection<PropertyMatch> newMatches)
{
final List<PropertyMatch> combinedMatches = new ArrayList<>(existingMatches);
combinedMatches.addAll(newMatches);
return combinedMatches.stream().collect(Collectors.toMap(
(propertyMatch) -> Arrays.asList(propertyMatch.getCode(), propertyMatch.getValue()),
Function.identity(),
(existingPropertyMatch, newPropertyMatch) -> {
existingPropertyMatch.getSpans().addAll(newPropertyMatch.getSpans());
return existingPropertyMatch;
},
HashMap::new
)).values();
}
private void mapAttributeMatches(final Map<String, Object> fieldsMap, final EntityKind entityKind, final List<PropertyMatch> matches)
......
......@@ -282,13 +282,13 @@ public class GlobalSearchCriteriaTranslator
buildHeadlineTsRank(sqlBuilder, stringValue, args, PROPERTIES_TABLE_ALIAS + PERIOD + VALUE_COLUMN,
VALUE_MATCH_RANK_ALIAS);
sqlBuilder.append(COMMA).append(SP);
sqlBuilder.append(COMMA).append(NL);
buildHeadlineTsRank(sqlBuilder, stringValue, args, CONTROLLED_VOCABULARY_TERMS_TABLE_ALIAS + PERIOD + CODE_COLUMN,
VALUE_MATCH_RANK_ALIAS);
sqlBuilder.append(COMMA).append(SP);
sqlBuilder.append(COMMA).append(NL);
buildHeadlineTsRank(sqlBuilder, stringValue, args,
CONTROLLED_VOCABULARY_TERMS_TABLE_ALIAS + PERIOD + LABEL_COLUMN, VALUE_MATCH_RANK_ALIAS);
sqlBuilder.append(COMMA).append(SP);
sqlBuilder.append(COMMA).append(NL);
buildHeadlineTsRank(sqlBuilder, stringValue, args,
CONTROLLED_VOCABULARY_TERMS_TABLE_ALIAS + PERIOD + DESCRIPTION_COLUMN, VALUE_MATCH_RANK_ALIAS);
}
......
......@@ -97,7 +97,7 @@ public class GlobalSearchTest extends AbstractTest
fo.withMatch();
final SearchResult<GlobalSearchObject> result = search(TEST_USER, criteria, fo);
assertSimpleOrStuff(result, 7);
assertSimpleOrStuff(result);
}
@Test
......@@ -111,7 +111,7 @@ public class GlobalSearchTest extends AbstractTest
fo.withMatch();
final SearchResult<GlobalSearchObject> result = search(TEST_USER, criteria, fo);
assertSimpleOrStuff(result, 8);
assertSimpleOrStuff(result);
}
@Test
......@@ -125,7 +125,7 @@ public class GlobalSearchTest extends AbstractTest
fo.withMatch();
final SearchResult<GlobalSearchObject> result = search(TEST_USER, criteria, fo);
assertSimpleOrStuff(result, 7);
assertSimpleOrStuff(result);
}
@Test
......@@ -165,7 +165,7 @@ public class GlobalSearchTest extends AbstractTest
fo.withMatch();
final SearchResult<GlobalSearchObject> result = search(TEST_USER, criteria, fo);
assertSimpleOrStuff(result, 8);
assertSimpleOrStuff(result);
}
@Test
......@@ -975,10 +975,10 @@ public class GlobalSearchTest extends AbstractTest
assertSample(iter.next(), "200902091250077-1026", "/CISD/CP-TEST-2", "Property 'Comment': extremely simple stuff");
}
private void assertSimpleOrStuff(final SearchResult<GlobalSearchObject> result, final int expectedResultsCount)
private void assertSimpleOrStuff(final SearchResult<GlobalSearchObject> result)
{
final List<GlobalSearchObject> objects = result.getObjects();
assertEquals(objects.size(), expectedResultsCount);
assertEquals(objects.size(), 7);
// Even though we have 8 results, one of them has two matches. Therefore, we need just 7 search objects.
final GlobalSearchObject[] searchObjects = new GlobalSearchObject[] {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment