diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/SearchResultSorterByScore.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/SearchResultSorterByScore.java index 68c4801739651f089beae47b1ed432d399af477f..779bc35e8aa8fb7c39ab33e69d3fe0ab565576e0 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/SearchResultSorterByScore.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/SearchResultSorterByScore.java @@ -44,45 +44,26 @@ public class SearchResultSorterByScore implements ISearchResultSorter return; } - // 1. Get terms to use as input for the main algorithm + // 1. Get terms and boosts to use as input for the main algorithm List<Pattern> partialMatchTerms = new ArrayList<Pattern>(); List<String> exactMatchTerms = new ArrayList<String>(); List<Boost> boosts = new ArrayList<Boost>(); + for (DetailedSearchCriterion criterion : criteria.getCriteria()) { + // Full Index partialMatchTerms.add(getPartialMatchTerm(criterion.getValue())); exactMatchTerms.add(getExactMatchTerm(criterion.getValue())); + boosts.add(getBoostForCriterion(criterion, 10)); + + // Split Index + String[] splitIndexes = criterion.getValue().replace("*", " ").replace("?", " ").replaceAll("\\s+", " ").trim().split(" "); - switch (criterion.getField().getKind()) + for (String splitIndex : splitIndexes) { - case ANY_FIELD: - boosts.add(new Boost(1, 1, 1, 1, null)); - break; - case ANY_PROPERTY: - boosts.add(new Boost(0, 0, 1, 1, null)); - break; - case PROPERTY: - boosts.add(new Boost(0, 0, 0, 1, criterion.getField().getPropertyCode())); - break; - case ATTRIBUTE: - if (criterion.getField().getAttributeCode().equalsIgnoreCase("code")) - { - boosts.add(new Boost(1, 0, 0, 0, null)); // Attribute code - } else if ( // TODO FIX hard coded types, will be clever to not naming the same thing differently internally to avoid this. - criterion.getField().getAttributeCode().equalsIgnoreCase("sample_type") - || criterion.getField().getAttributeCode().equalsIgnoreCase("data_set_type") - || criterion.getField().getAttributeCode().equalsIgnoreCase("material_type") - || criterion.getField().getAttributeCode().equalsIgnoreCase("experiment_type")) - { - boosts.add(new Boost(0, 1, 0, 0, null)); // Attribute type code - } else - { - boosts.add(new Boost(1, 1, 1, 1, null)); // Other attributes not supported, default to general case - } - break; - case REGISTRATOR: - boosts.add(new Boost(1, 1, 1, 1, null)); // Registrator not supported, default to general case - break; + partialMatchTerms.add(getPartialMatchTerm(splitIndex)); + exactMatchTerms.add(getExactMatchTerm(splitIndex)); + boosts.add(getBoostForCriterion(criterion, 1)); } } @@ -113,6 +94,8 @@ public class SearchResultSorterByScore implements ISearchResultSorter } } }); + + System.out.println(entitiesToSort); } private int getScore(IEntitySearchResult entity, List<Pattern> partialMatchTerms, List<String> exactMatchTerms, List<Boost> boosts) @@ -157,7 +140,7 @@ public class SearchResultSorterByScore implements ISearchResultSorter } } } - // For development System.out.println(entity.getCode() + " " + score); + System.out.println(entity.getCode() + " " + score); return score; } @@ -209,6 +192,38 @@ public class SearchResultSorterByScore implements ISearchResultSorter } + public Boost getBoostForCriterion(DetailedSearchCriterion criterion, int boost) + { + switch (criterion.getField().getKind()) + { + case ANY_FIELD: + return new Boost(boost, boost, boost, boost, null); // Default case + case ANY_PROPERTY: + return new Boost(0, 0, boost, boost, null); + case PROPERTY: + return new Boost(0, 0, 0, boost, criterion.getField().getPropertyCode()); + case ATTRIBUTE: + if (criterion.getField().getAttributeCode().equalsIgnoreCase("code")) + { + return new Boost(boost, 0, 0, 0, null); // Attribute code + } else if ( // TODO FIX hard coded types, will be clever to not naming the same thing differently internally to avoid this. + criterion.getField().getAttributeCode().equalsIgnoreCase("sample_type") + || criterion.getField().getAttributeCode().equalsIgnoreCase("data_set_type") + || criterion.getField().getAttributeCode().equalsIgnoreCase("material_type") + || criterion.getField().getAttributeCode().equalsIgnoreCase("experiment_type")) + { + return new Boost(0, boost, 0, 0, null); // Attribute type code + } else + { + return new Boost(boost, boost, boost, boost, null); // Other attributes not supported, default to general case + } + case REGISTRATOR: + return new Boost(boost, boost, boost, boost, null); // Registrator not supported, default to general case + default: + return new Boost(boost, boost, boost, boost, null); // Default to general case + } + } + public Pattern getPartialMatchTerm(String term) { return Pattern.compile(("*" + term + "*").replace("*", ".*").replace("?", ".?"), Pattern.CASE_INSENSITIVE); diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/SearchResultSorterByScoreTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/SearchResultSorterByScoreTest.java index 2166a75632c9261d9ab7ae1263f060d7444cde58..698760b39e3aabae674970f2632524e945756488 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/SearchResultSorterByScoreTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/SearchResultSorterByScoreTest.java @@ -130,6 +130,23 @@ public class SearchResultSorterByScoreTest extends AssertJUnit assertEntities(entities, "CODE_4", "CODE_1", "CODE_2", "CODE_3"); } + @Test + public void testCriteriaPropForPropertiesWithSpaces() + { + // Entities Setup + List<EntitySearchResult> entities = new ArrayList<EntitySearchResult>(); + entities.add(createEntity("CODE_2", "TYPE_2", "ABC")); + entities.add(createEntity("CODE_1", "TYPE_1", "ABC ")); + entities.add(createEntity("CODE_3", "TYPE_3", "ABC", "DEF")); + entities.add(createEntity("CODE_4", "TYPE_4", "ABC \tDEF")); + + // Test hit only properties, partial and exact + sort(entities, getPropertyFieldCriterion("PROP_1", "ABC \tDEF")); + + // Verify results + assertEntities(entities, "CODE_4", "CODE_2", "CODE_3", "CODE_1"); + } + @Test public void testCriteriaAnyPropForProperties() { @@ -147,6 +164,23 @@ public class SearchResultSorterByScoreTest extends AssertJUnit assertEntities(entities, "CODE_1", "CODE_4", "CODE_3", "CODE_2"); } + @Test + public void testCriteriaAnyPropForPropertiesWithSpaces() + { + // Entities Setup + List<EntitySearchResult> entities = new ArrayList<EntitySearchResult>(); + entities.add(createEntity("CODE_2", "TYPE_2", "ABC")); + entities.add(createEntity("CODE_1", "TYPE_1", "ABC ")); + entities.add(createEntity("CODE_3", "TYPE_3", "ABC", "DEF")); + entities.add(createEntity("CODE_4", "TYPE_4", "ABC \tDEF")); + + // Test hit only properties, partial and exact + sort(entities, getAnyPropertyFieldCriterion("ABC \tDEF")); + + // Verify results + assertEntities(entities, "CODE_4", "CODE_3", "CODE_2", "CODE_1"); + } + @Test public void testCriteriaAnyAll() {