mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
Fix: default sort option (lastModified) for discovery
This commit is contained in:
@@ -9,6 +9,7 @@ package org.dspace.discovery.configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -22,6 +23,11 @@ public class DiscoverySortConfiguration {
|
||||
|
||||
private List<DiscoverySortFieldConfiguration> sortFields = new ArrayList<DiscoverySortFieldConfiguration>();
|
||||
|
||||
/**
|
||||
* Default sort configuration to use when needed
|
||||
*/
|
||||
@Nullable private DiscoverySortFieldConfiguration defaultSortField;
|
||||
|
||||
public List<DiscoverySortFieldConfiguration> getSortFields() {
|
||||
return sortFields;
|
||||
}
|
||||
@@ -30,6 +36,14 @@ public class DiscoverySortConfiguration {
|
||||
this.sortFields = sortFields;
|
||||
}
|
||||
|
||||
public DiscoverySortFieldConfiguration getDefaultSortField() {
|
||||
return defaultSortField;
|
||||
}
|
||||
|
||||
public void setDefaultSortField(DiscoverySortFieldConfiguration configuration) {
|
||||
this.defaultSortField = configuration;
|
||||
}
|
||||
|
||||
public DiscoverySortFieldConfiguration getSortFieldConfiguration(String sortField) {
|
||||
if (StringUtils.isBlank(sortField)) {
|
||||
return null;
|
||||
|
@@ -332,7 +332,9 @@ public class DiscoverQueryBuilder implements InitializingBean {
|
||||
}
|
||||
|
||||
private String getDefaultSortDirection(DiscoverySortConfiguration searchSortConfiguration, String sortOrder) {
|
||||
if (Objects.nonNull(searchSortConfiguration.getSortFields()) &&
|
||||
if (searchSortConfiguration.getDefaultSortField() != null) {
|
||||
sortOrder = searchSortConfiguration.getDefaultSortField().getDefaultSortOrder().name();
|
||||
} else if (Objects.nonNull(searchSortConfiguration.getSortFields()) &&
|
||||
!searchSortConfiguration.getSortFields().isEmpty()) {
|
||||
sortOrder = searchSortConfiguration.getSortFields().get(0).getDefaultSortOrder().name();
|
||||
}
|
||||
@@ -342,7 +344,9 @@ public class DiscoverQueryBuilder implements InitializingBean {
|
||||
private String getDefaultSortField(DiscoverySortConfiguration searchSortConfiguration) {
|
||||
String sortBy;// Attempt to find the default one, if none found we use SCORE
|
||||
sortBy = "score";
|
||||
if (Objects.nonNull(searchSortConfiguration.getSortFields()) &&
|
||||
if (searchSortConfiguration.getDefaultSortField() != null) {
|
||||
sortBy = searchSortConfiguration.getDefaultSortField().getMetadataField();
|
||||
} else if (Objects.nonNull(searchSortConfiguration.getSortFields()) &&
|
||||
!searchSortConfiguration.getSortFields().isEmpty()) {
|
||||
DiscoverySortFieldConfiguration defaultSort = searchSortConfiguration.getSortFields().get(0);
|
||||
if (StringUtils.isBlank(defaultSort.getMetadataField())) {
|
||||
|
@@ -8,13 +8,16 @@
|
||||
package org.dspace.discovery;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.dspace.AbstractIntegrationTestWithDatabase;
|
||||
@@ -24,6 +27,7 @@ import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.builder.ClaimedTaskBuilder;
|
||||
import org.dspace.builder.CollectionBuilder;
|
||||
import org.dspace.builder.CommunityBuilder;
|
||||
import org.dspace.builder.EPersonBuilder;
|
||||
import org.dspace.builder.ItemBuilder;
|
||||
import org.dspace.builder.PoolTaskBuilder;
|
||||
import org.dspace.builder.WorkflowItemBuilder;
|
||||
@@ -39,6 +43,8 @@ import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.CollectionService;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.content.service.WorkspaceItemService;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoverySortFieldConfiguration;
|
||||
import org.dspace.discovery.indexobject.IndexableClaimedTask;
|
||||
import org.dspace.discovery.indexobject.IndexableCollection;
|
||||
import org.dspace.discovery.indexobject.IndexableItem;
|
||||
@@ -731,6 +737,68 @@ public class DiscoveryIT extends AbstractIntegrationTestWithDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test designed to check if default sort option for Discovery is working, using <code>workspace</code>
|
||||
* DiscoveryConfiguration <br/>
|
||||
* <b>Note</b>: this test will be skipped if <code>workspace</code> do not have a default sort option set and of
|
||||
* metadataType <code>dc_date_accessioned</code> or <code>lastModified</code>
|
||||
* @throws SearchServiceException
|
||||
*/
|
||||
@Test
|
||||
public void searchWithDefaultSortServiceTest() throws SearchServiceException {
|
||||
|
||||
DiscoveryConfiguration workspaceConf = SearchUtils.getDiscoveryConfiguration("workspace", null);
|
||||
// Skip if no default sort option set for workspaceConf
|
||||
if (workspaceConf.getSearchSortConfiguration().getDefaultSortField() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
DiscoverySortFieldConfiguration defaultSortField =
|
||||
workspaceConf.getSearchSortConfiguration().getDefaultSortField();
|
||||
|
||||
// Populate the testing objects: create items in eperson's workspace and perform search in it
|
||||
int numberItems = 10;
|
||||
context.turnOffAuthorisationSystem();
|
||||
EPerson submitter = EPersonBuilder.createEPerson(context).withEmail("submitter@example.org").build();
|
||||
context.setCurrentUser(submitter);
|
||||
Community community = CommunityBuilder.createCommunity(context).build();
|
||||
Collection collection = CollectionBuilder.createCollection(context, community).build();
|
||||
for (int i = 0; i < numberItems; i++) {
|
||||
ItemBuilder.createItem(context, collection)
|
||||
.withTitle("item " + i)
|
||||
.build();
|
||||
}
|
||||
|
||||
// Build query with default parameters (except for workspaceConf)
|
||||
DiscoverQuery discoverQuery = SearchUtils.getQueryBuilder()
|
||||
.buildQuery(context, new IndexableCollection(collection), workspaceConf,"",null,"Item",null,null,
|
||||
null,null);
|
||||
|
||||
DiscoverResult result = searchService.search(context, discoverQuery);
|
||||
|
||||
if (defaultSortField.getMetadataField().equals("dc_date_accessioned")) {
|
||||
// Verify that search results are sort by dc_date_accessioned
|
||||
LinkedList<String> dc_date_accesioneds = result.getIndexableObjects().stream()
|
||||
.map(o -> ((Item) o.getIndexedObject()).getMetadata())
|
||||
.map(l -> l.stream().filter(m -> m.getMetadataField().toString().equals("dc_date_accessioned"))
|
||||
.map(m -> m.getValue()).findFirst().orElse("")
|
||||
)
|
||||
.collect(Collectors.toCollection(LinkedList::new));
|
||||
assertFalse(dc_date_accesioneds.isEmpty());
|
||||
for (int i = 1; i < dc_date_accesioneds.size() - 1; i++) {
|
||||
assertTrue(dc_date_accesioneds.get(i).compareTo(dc_date_accesioneds.get(i + 1)) >= 0);
|
||||
}
|
||||
} else if (defaultSortField.getMetadataField().equals("lastModified")) {
|
||||
LinkedList<String> lastModifieds = result.getIndexableObjects().stream()
|
||||
.map(o -> ((Item) o.getIndexedObject()).getLastModified().toString())
|
||||
.collect(Collectors.toCollection(LinkedList::new));
|
||||
assertFalse(lastModifieds.isEmpty());
|
||||
for (int i = 1; i < lastModifieds.size() - 1; i++) {
|
||||
assertTrue(lastModifieds.get(i).compareTo(lastModifieds.get(i + 1)) >= 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void assertSearchQuery(String resourceType, int size) throws SearchServiceException {
|
||||
assertSearchQuery(resourceType, size, size, 0, -1);
|
||||
}
|
||||
|
@@ -80,6 +80,15 @@ public class DiscoverConfigurationConverter
|
||||
sortOption.setSortOrder(discoverySearchSortConfiguration.getDefaultSortOrder().name());
|
||||
searchConfigurationRest.addSortOption(sortOption);
|
||||
}
|
||||
|
||||
DiscoverySortFieldConfiguration defaultSortField = searchSortConfiguration.getDefaultSortField();
|
||||
if (defaultSortField != null) {
|
||||
SearchConfigurationRest.SortOption sortOption = new SearchConfigurationRest.SortOption();
|
||||
sortOption.setName(defaultSortField.getMetadataField());
|
||||
sortOption.setActualName(defaultSortField.getType());
|
||||
sortOption.setSortOrder(defaultSortField.getDefaultSortOrder().name());
|
||||
searchConfigurationRest.setDefaultSortOption(sortOption);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -31,6 +31,8 @@ public class SearchConfigurationRest extends BaseObjectRest<String> {
|
||||
private List<Filter> filters = new LinkedList<>();
|
||||
private List<SortOption> sortOptions = new LinkedList<>();
|
||||
|
||||
private SortOption defaultSortOption;
|
||||
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
@@ -75,6 +77,14 @@ public class SearchConfigurationRest extends BaseObjectRest<String> {
|
||||
return sortOptions;
|
||||
}
|
||||
|
||||
public SortOption getDefaultSortOption() {
|
||||
return defaultSortOption;
|
||||
}
|
||||
|
||||
public void setDefaultSortOption(SortOption defaultSortOption) {
|
||||
this.defaultSortOption = defaultSortOption;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
return (object instanceof SearchConfigurationRest &&
|
||||
|
@@ -1286,8 +1286,10 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
//Update this test since dc.date.accessioned is now configured for workspace configuration,
|
||||
// which will return status 400 instead of 422 if left unchanged
|
||||
getClient().perform(get("/api/discover/search/objects")
|
||||
.param("sort", "dc.date.accessioned, ASC")
|
||||
.param("sort", "person.familyName, ASC")
|
||||
.param("configuration", "workspace"))
|
||||
.andExpect(status().isUnprocessableEntity());
|
||||
}
|
||||
|
@@ -115,6 +115,8 @@ public class RestDiscoverQueryBuilderTest {
|
||||
|
||||
sortConfiguration.setSortFields(listSortField);
|
||||
|
||||
sortConfiguration.setDefaultSortField(defaultSort);
|
||||
|
||||
discoveryConfiguration.setSearchSortConfiguration(sortConfiguration);
|
||||
|
||||
DiscoverySearchFilterFacet subjectFacet = new DiscoverySearchFilterFacet();
|
||||
@@ -167,6 +169,19 @@ public class RestDiscoverQueryBuilderTest {
|
||||
page.getOffset(), "SCORE", "ASC");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSortByDefaultSortField() throws Exception {
|
||||
page = PageRequest.of(2, 10, Sort.Direction.DESC, "dc.date.accessioned");
|
||||
restQueryBuilder.buildQuery(context, null, discoveryConfiguration, null, null, emptyList(), page);
|
||||
|
||||
verify(discoverQueryBuilder, times(1))
|
||||
.buildQuery(context, null, discoveryConfiguration, null, emptyList(), emptyList(),
|
||||
page.getPageSize(), page.getOffset(),
|
||||
discoveryConfiguration.getSearchSortConfiguration().getDefaultSortField().getMetadataField(),
|
||||
discoveryConfiguration.getSearchSortConfiguration().getDefaultSortField()
|
||||
.getDefaultSortOrder().name().toUpperCase());
|
||||
}
|
||||
|
||||
@Test(expected = DSpaceBadRequestException.class)
|
||||
public void testCatchIllegalArgumentException() throws Exception {
|
||||
when(discoverQueryBuilder.buildQuery(any(), any(), any(), any(), any(), anyList(), any(), any(), any(),
|
||||
|
@@ -865,8 +865,11 @@
|
||||
<!--The sort filters for the discovery search-->
|
||||
<property name="searchSortConfiguration">
|
||||
<bean class="org.dspace.discovery.configuration.DiscoverySortConfiguration">
|
||||
<!--The default sort filter to use for the initial workspace loading-->
|
||||
<property name="defaultSortField" ref="sortDateAccessioned" />
|
||||
<property name="sortFields">
|
||||
<list>
|
||||
<ref bean="sortDateAccessioned" />
|
||||
<ref bean="sortScore" />
|
||||
<ref bean="sortTitle" />
|
||||
<ref bean="sortDateIssued" />
|
||||
@@ -938,6 +941,8 @@
|
||||
<!--The sort filters for the discovery search-->
|
||||
<property name="searchSortConfiguration">
|
||||
<bean class="org.dspace.discovery.configuration.DiscoverySortConfiguration">
|
||||
<!--The default sort filter to use for the initial workspace loading-->
|
||||
<property name="defaultSortField" ref="sortLastModified" />
|
||||
<property name="sortFields">
|
||||
<list>
|
||||
<ref bean="sortLastModified" />
|
||||
@@ -1015,6 +1020,7 @@
|
||||
<bean class="org.dspace.discovery.configuration.DiscoverySortConfiguration">
|
||||
<property name="sortFields">
|
||||
<list>
|
||||
<ref bean="sortLastModified" />
|
||||
<ref bean="sortScore" />
|
||||
<ref bean="sortTitle" />
|
||||
<ref bean="sortDateIssued" />
|
||||
|
@@ -283,6 +283,7 @@
|
||||
<!-- used by the DSpace Discovery Solr Indexer to track the last time a document was indexed -->
|
||||
<field name="SolrIndexer.lastIndexed" type="date" indexed="true" stored="true" default="NOW" multiValued="false" omitNorms="true" />
|
||||
<field name="lastModified" type="date" indexed="true" stored="true" default="NOW" multiValued="false" omitNorms="true" />
|
||||
<copyField source="lastModified" dest="lastModified_dt" />
|
||||
|
||||
<!-- used to filter out items that are older versions of another item -->
|
||||
<field name="latestVersion" type="boolean" indexed="true" stored="true" default="true" multiValued="false" omitNorms="true"/>
|
||||
|
Reference in New Issue
Block a user