Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ public class SolrServiceImpl implements SearchService, IndexingService {
// facet by indexing "each word to end of value' partial value
public static final String SOLR_FIELD_SUFFIX_FACET_PREFIXES = "_prefix";

// Suffix of the solr field used to index the facet/filter so that the facet search can search all word in a
// facet.
private static final String SOLR_FACET_FIELD_ALL_VALUES_SUFFIX = "_filter";

// List of all facets which will return facet value with splitter.
private ArrayList<String> allValuesFacetList = new ArrayList<>();

@Autowired
protected ContentServiceFactory contentServiceFactory;
@Autowired
Expand Down Expand Up @@ -1400,12 +1407,22 @@ protected String transformFacetField(DiscoverFacetField facetFieldConfig, String
}
} else if (facetFieldConfig.getType().equals(DiscoveryConfigurationParameters.TYPE_HIERARCHICAL)) {
if (removePostfix) {
// If the current field is configured to show all values instead of only the top level values
if (this.getFacetsToShowAllValues().contains(
StringUtils.substringBeforeLast(field, SOLR_FACET_FIELD_ALL_VALUES_SUFFIX))) {
return StringUtils.substringBeforeLast(field, SOLR_FACET_FIELD_ALL_VALUES_SUFFIX);
}
return StringUtils.substringBeforeLast(field, "_tax_");
} else {
// If the current field is configured to show all values instead of only the top level values
if (this.getFacetsToShowAllValues().contains(field)) {
return field + SOLR_FACET_FIELD_ALL_VALUES_SUFFIX;
}
//Only display top level filters !
return field + "_tax_0_filter";
}
} else if (facetFieldConfig.getType().equals(DiscoveryConfigurationParameters.TYPE_AUTHORITY)) {

if (removePostfix) {
return field.substring(0, field.lastIndexOf("_acid"));
} else {
Expand Down Expand Up @@ -1603,4 +1620,15 @@ public String calculateExtremeValue(Context context, String valueField,
return null;
}

/**
* Return or load the configuration property `discovery.solr.facets.allvalues` as a list.
*/
private ArrayList<String> getFacetsToShowAllValues() {
if (CollectionUtils.isEmpty(allValuesFacetList)) {
String[] allValuesFacetArray = configurationService.getArrayProperty("discovery.solr.facets.allvalues");
Collections.addAll(allValuesFacetList, allValuesFacetArray);
}
return allValuesFacetList;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<!-- Same as the "default" configuration, but does NOT filter out older versions of items -->
<!-- Used to display related items on single-item pages, because a relationship does not always point to the latest version of the related item -->
<entry key="default-relationships" value-ref="defaultRelationshipsConfiguration" />
<entry key="homepage" value-ref="homepageConfiguration" />
<!--<entry key="123456789/7621" value-ref="defaultConfiguration"/>-->
<!-- Used to show filters and results on MyDSpace -->
<!-- Do not change the id of special entries or else they won't work -->
Expand Down Expand Up @@ -144,6 +145,166 @@
</property>
</bean>

<bean id="homepageConfiguration" class="org.dspace.discovery.configuration.DiscoveryConfiguration" scope="prototype">
<!--Which sidebar facets are to be displayed-->
<property name="sidebarFacets">
<list>
<ref bean="searchFilterAuthor" />
<ref bean="searchFilterSubjectFirstValue" />
<!-- <ref bean="searchFilterIssued" />-->
<ref bean="searchFilterRights" />
<ref bean="searchFilterLanguage" />
<ref bean="searchFilterContentInOriginalBundle"/>
<ref bean="searchFilterEntityType"/>
<ref bean="searchFilterItemsCommunity"/>
</list>
</property>
<!-- Set TagCloud configuration per discovery configuration -->
<property name="tagCloudFacetConfiguration" ref="defaultTagCloudFacetConfiguration"/>
<!--The search filters which can be used on the discovery search page-->
<property name="searchFilters">
<list>
<ref bean="searchFilterTitle" />
<ref bean="searchFilterAuthor" />
<ref bean="searchFilterSubject" />
<ref bean="searchFilterSubjectFirstValue" />
<!-- <ref bean="searchFilterIssued" />-->
<ref bean="searchFilterContentInOriginalBundle"/>
<ref bean="searchFilterFileNameInOriginalBundle" />
<ref bean="searchFilterFileDescriptionInOriginalBundle" />
<ref bean="searchFilterEntityType"/>
<ref bean="searchFilterIsAuthorOfPublicationRelation"/>
<ref bean="searchFilterIsProjectOfPublicationRelation"/>
<ref bean="searchFilterIsOrgUnitOfPublicationRelation"/>
<ref bean="searchFilterIsPublicationOfJournalIssueRelation"/>
<ref bean="searchFilterIsJournalOfPublicationRelation"/>
<ref bean="searchFilterRights" />
<ref bean="searchFilterLanguage" />
<ref bean="searchFilterItemsCommunity"/>
<ref bean="searchFilterType"/>
<ref bean="searchFilterPublisher"/>
</list>
</property>
<!--The sort filters for the discovery search-->
<property name="searchSortConfiguration">
<bean class="org.dspace.discovery.configuration.DiscoverySortConfiguration">
<property name="sortFields">
<list>
<ref bean="sortScore" />
<ref bean="sortTitleAsc" />
<ref bean="sortTitleDesc" />
<ref bean="sortDateIssuedAsc" />
<ref bean="sortDateIssuedDesc" />
<ref bean="sortDateAccessioned"/>
</list>
</property>
</bean>
</property>
<!--Any default filter queries, these filter queries will be used for all
queries done by discovery for this configuration -->
<property name="defaultFilterQueries">
<list>
<!--Only find items, communities and collections-->
<value>(search.resourcetype:Item) OR search.resourcetype:Collection OR search.resourcetype:Community</value>
<value>-withdrawn:true AND -discoverable:false</value>
</list>
</property>
<!--The configuration for the recent submissions-->
<property name="recentSubmissionConfiguration">
<bean class="org.dspace.discovery.configuration.DiscoveryRecentSubmissionsConfiguration">
<property name="metadataSortField" value="dc.date.accessioned" />
<property name="type" value="date"/>
<property name="max" value="20"/>
<!-- If enabled the collection home page will not display metadata but show a pageable list of recent submissions -->
<property name="useAsHomePage" value="false"/>
</bean>
</property>
<!--Default result per page -->
<property name="defaultRpp" value="10" />
<property name="hitHighlightingConfiguration">
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightingConfiguration">
<property name="metadataFields">
<list>
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration">
<property name="field" value="dc.contributor.author"/>
<property name="snippets" value="5"/>
</bean>
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration">
<property name="field" value="dspace.entity.type"/>
<property name="snippets" value="5"/>
</bean>
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration">
<property name="field" value="person.identifier.jobtitle"/>
<property name="snippets" value="5"/>
</bean>
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration">
<property name="field" value="project.identifier.name"/>
<property name="snippets" value="5"/>
</bean>
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration">
<property name="field" value="dc.description.abstract"/>
<property name="maxSize" value="250"/>
<property name="snippets" value="2"/>
</bean>
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration">
<property name="field" value="dc.title"/>
<property name="snippets" value="5"/>
</bean>
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration">
<property name="field" value="organization.legalName"/>
<property name="snippets" value="5"/>
</bean>
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration">
<property name="field" value="person.givenName"/>
<property name="snippets" value="5"/>
</bean>
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration">
<property name="field" value="person.familyName"/>
<property name="snippets" value="5"/>
</bean>
<!-- By default, full text snippets are disabled, as snippets of embargoed/restricted bitstreams
may appear in search results when the Item is public. See DS-3498
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration">
<property name="field" value="project.identifier.status"/>
<property name="snippets" value="5"/>
</bean>
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration">
<property name="field" value="orgunit.identifier.name"/>
<property name="snippets" value="5"/>
</bean>
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration">
<property name="field" value="orgunit.identifier.description"/>
<property name="maxSize" value="250"/>
<property name="snippets" value="5"/>
</bean>
-->
</list>
</property>
</bean>
</property>
<property name="moreLikeThisConfiguration">
<bean class="org.dspace.discovery.configuration.DiscoveryMoreLikeThisConfiguration">
<property name="similarityMetadataFields">
<list>
<value>dc.title</value>
<value>dc.contributor.author</value>
<value>dc.creator</value>
<value>dc.contributor.other</value>
<value>dc.subject</value>
</list>
</property>
<!--The minimum number of matching terms across the metadata fields above before an item is found as related -->
<property name="minTermFrequency" value="5"/>
<!--The maximum number of related items displayed-->
<property name="max" value="3"/>
<!--The minimum word length below which words will be ignored-->
<property name="minWordLength" value="5"/>
</bean>
</property>
<!-- When true a "did you mean" example will be displayed, value can be true or false -->
<property name="spellCheckEnabled" value="true"/>
</bean>

<bean id="discovery-parent-community-1" class="org.dspace.discovery.configuration.DiscoveryConfiguration" scope="prototype">
<property name="id" value="discovery-parent-community-1"/>
<!--Which sidebar facets are to be displayed-->
Expand Down Expand Up @@ -1114,5 +1275,18 @@
<property name="pageSize" value="10"/>
<property name="exposeMinAndMaxValue" value="true"/>
</bean>
<bean id="searchFilterSubjectFirstValue" class="org.dspace.discovery.configuration.HierarchicalSidebarFacetConfiguration">
<property name="indexFieldName" value="subjectFirstValue"/>
<property name="metadataFields">
<list>
<value>dc.subject.*</value>
</list>
</property>
<property name="facetLimit" value="5"/>
<property name="sortOrderSidebar" value="COUNT"/>
<property name="sortOrderFilterPage" value="COUNT"/>
<property name="splitter" value="::"/>
<property name="skipFirstNodeLevel" value="false"/>

</bean>
</beans>
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,8 @@ public void discoverSearchTest() throws Exception {
SearchFilterMatcher.clarinLicenseRightsFilter(),
SearchFilterMatcher.clarinItemsLanguageFilter(),
SearchFilterMatcher.clarinItemsCommunityFilter(),
SearchFilterMatcher.clarinItemsTypeFilter()
SearchFilterMatcher.clarinItemsTypeFilter(),
SearchFilterMatcher.clarinSubjectFirstValueFilter()
)))
//These sortOptions need to be present as it's the default in the configuration
.andExpect(jsonPath("$.sortOptions", contains(
Expand Down Expand Up @@ -5947,4 +5948,112 @@ public void discoverFacetsTestWithDsoTypeTest() throws Exception {
.andExpect(jsonPath("$._embedded.values").value(Matchers.hasSize(1)));

}

@Test
public void showFacetValuesWithSplitterInSearchPage() throws Exception {
context.turnOffAuthorisationSystem();

parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community").build();

Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
.withName("Collection 1").build();

ItemBuilder.createItem(context, col1)
.withTitle("Public item 1")
.withIssueDate("2017-10-17")
.withAuthor("Smith, Donald")
.withSubject("People")
.build();

ItemBuilder.createItem(context, col1)
.withTitle("Public item 2")
.withIssueDate("2020-02-13")
.withAuthor("Doe, Jane")
.withSubject("People::Jane")
.build();

ItemBuilder.createItem(context, col1)
.withTitle("Public item 2")
.withIssueDate("2020-02-13")
.withAuthor("Doe, Jane")
.withSubject("People::Jane")
.build();

context.restoreAuthSystemState();

getClient().perform(get("/api/discover/facets/subject"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.type", is("discover")))
.andExpect(jsonPath("$.name", is("subject")))
.andExpect(jsonPath("$.facetType", is("hierarchical")))
.andExpect(jsonPath("$.scope", is(emptyOrNullString())))
.andExpect(jsonPath("$._links.self.href",
containsString("api/discover/facets/subject")))
.andExpect(jsonPath("$._embedded.values[0].label", is("People")))
.andExpect(jsonPath("$._embedded.values[0].count", is(3)))
.andExpect(jsonPath("$._embedded.values[1].label", is("People::Jane")))
.andExpect(jsonPath("$._embedded.values[1].count", is(2)))
.andExpect(jsonPath("$", JsonPathMatchers.hasNoJsonPath("_embedded.values[2].label")))
.andExpect(jsonPath("$", JsonPathMatchers.hasNoJsonPath("_embedded.values[2].count")))
.andExpect(jsonPath("$._embedded.values").value(Matchers.hasSize(2)));
}

@Test
public void doNotShowFacetValuesWithSplitterInHomePage() throws Exception {
context.turnOffAuthorisationSystem();

parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community").build();

Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
.withName("Collection 1").build();

ItemBuilder.createItem(context, col1)
.withTitle("Public item 1")
.withIssueDate("2017-10-17")
.withAuthor("Smith, Donald")
.withSubject("People")
.build();

ItemBuilder.createItem(context, col1)
.withTitle("Public item 2")
.withIssueDate("2020-02-13")
.withAuthor("Doe, Jane")
.withSubject("People::Jane")
.build();

ItemBuilder.createItem(context, col1)
.withTitle("Public item 2")
.withIssueDate("2020-02-13")
.withAuthor("Doe, Jane")
.withSubject("People::Jane")
.build();

ItemBuilder.createItem(context, col1)
.withTitle("Public item 2")
.withIssueDate("2020-02-13")
.withAuthor("Doe, Jane")
.withSubject("Another subject")
.build();

context.restoreAuthSystemState();

getClient().perform(get("/api/discover/facets/subjectFirstValue")
.param("configuration", "homepage"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.type", is("discover")))
.andExpect(jsonPath("$.name", is("subjectFirstValue")))
.andExpect(jsonPath("$.facetType", is("hierarchical")))
.andExpect(jsonPath("$.scope", is(emptyOrNullString())))
.andExpect(jsonPath("$._links.self.href",
containsString("api/discover/facets/subjectFirstValue")))
.andExpect(jsonPath("$._embedded.values[0].label", is("People")))
.andExpect(jsonPath("$._embedded.values[0].count", is(3)))
.andExpect(jsonPath("$._embedded.values[1].label", is("Another subject")))
.andExpect(jsonPath("$._embedded.values[1].count", is(1)))
.andExpect(jsonPath("$", JsonPathMatchers.hasNoJsonPath("_embedded.values[2].label")))
.andExpect(jsonPath("$", JsonPathMatchers.hasNoJsonPath("_embedded.values[2].count")))
.andExpect(jsonPath("$._embedded.values").value(Matchers.hasSize(2)));
}
}
Loading