[DSCR-22] Discovery module back end rewrite to support discovery without solr.

git-svn-id: http://scm.dspace.org/svn/repo/dspace/trunk@6463 9c30dcfa-912a-0410-8fc2-9e0234be79fd
This commit is contained in:
Mark Diggory
2011-07-13 23:20:42 +00:00
parent 128f8cbabc
commit c13c6022e3
34 changed files with 1933 additions and 1324 deletions

View File

@@ -38,18 +38,6 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
@@ -121,4 +109,4 @@
</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-discovery/dspace-discovery-provider</url>
</scm>
</project>
</project>

View File

@@ -0,0 +1,51 @@
package org.dspace.discovery;
/**
* This class represents a filter query for discovery and can contain the following objects:
* The field in which we are searching
* The query the query which the filter query is using
* The displayed value
*
* @author Kevin Van de Velde (kevin at atmire dot com)
*
*/
public class DiscoverFilterQuery {
private String field;
private String filterQuery;
private String displayedValue;
public DiscoverFilterQuery() {
}
public DiscoverFilterQuery(String field, String filterQuery, String displayedValue) {
this.field = field;
this.filterQuery = filterQuery;
this.displayedValue = displayedValue;
}
public void setField(String field) {
this.field = field;
}
public void setFilterQuery(String filterQuery) {
this.filterQuery = filterQuery;
}
public void setDisplayedValue(String displayedValue) {
this.displayedValue = displayedValue;
}
public String getField() {
return field;
}
public String getFilterQuery() {
return filterQuery;
}
public String getDisplayedValue() {
return displayedValue;
}
}

View File

@@ -0,0 +1,279 @@
package org.dspace.discovery;
import java.util.*;
/**
* This class represents a query which the discovery backend can use
*
* @author Kevin Van de Velde (kevin at atmire dot com)
*
*/
public class DiscoverQuery {
/** Main attributes for the discovery query **/
private String query;
private List<String> filterQueries;
private int DSpaceObjectFilter = -1;
private List<String> fieldPresentQueries;
private int start = 0;
private int maxResults = -1;
/** Attributes used for sorting of results **/
public enum SORT_ORDER {
desc,
asc
}
private String sortField;
private SORT_ORDER sortOrder;
/** Attributes required for the faceting of values **/
private List<FacetFieldConfig> facetFields;
private List<String> facetQueries;
private int facetLimit = -1;
private int facetMinCount = -1;
private int facetOffset = 0;
public enum FACET_SORT {
INDEX,
COUNT
}
private FACET_SORT facetSort;
/** Used when you want to search for a specific field value **/
private List<String> searchFields;
/** Misc attributes can be implementation dependent **/
private Map<String, List<String>> properties;
public DiscoverQuery() {
//Initialize all our lists
this.filterQueries = new ArrayList<String>();
this.fieldPresentQueries = new ArrayList<String>();
this.facetFields = new ArrayList<FacetFieldConfig>();
this.facetQueries = new ArrayList<String>();
this.searchFields = new ArrayList<String>();
//Use a linked hashmap since sometimes insertion order might matter
this.properties = new LinkedHashMap<String, List<String>>();
this.facetSort = FACET_SORT.COUNT;
}
public void setQuery(String query) {
this.query = query;
}
public String getQuery() {
return query;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public void setSortField(String sortField, SORT_ORDER sortOrder){
this.sortField = sortField;
this.sortOrder = sortOrder;
}
public String getSortField() {
return sortField;
}
public SORT_ORDER getSortOrder() {
return sortOrder;
}
/**
* Sets the DSpace object filter, must be an DSpace Object type integer
* can be used to only return objects from a certain DSpace Object type
* @param DSpaceObjectFilter the DSpace object filer
*/
public void setDSpaceObjectFilter(int DSpaceObjectFilter) {
this.DSpaceObjectFilter = DSpaceObjectFilter;
}
/**
* Gets the DSpace object filter
* can be used to only return objects from a certain DSpace Object type
* @return the DSpace object filer
*/
public int getDSpaceObjectFilter() {
return DSpaceObjectFilter;
}
/**
* The maximum number of results returned by this query
* @return the number of results
*/
public int getMaxResults() {
return maxResults;
}
/**
* Sets the maximum number of results by this query
* @param maxResults the number of results
*/
public void setMaxResults(int maxResults) {
this.maxResults = maxResults;
}
/**
* Adds new filter queries
* @param filterQueries the filter queries to be added
*/
public void addFilterQueries(String ...filterQueries){
this.filterQueries.addAll(Arrays.asList(filterQueries));
}
/**
* Returns the filter queries
* @return the filter queries in a list
*/
public List<String> getFilterQueries() {
return filterQueries;
}
/**
* Adds a query that will ensure that a certain field is present in the index
* @param fieldPresentQueries the queries to be added
*/
public void addFieldPresentQueries(String ...fieldPresentQueries){
this.fieldPresentQueries.addAll(Arrays.asList(fieldPresentQueries));
}
public List<String> getFieldPresentQueries() {
return fieldPresentQueries;
}
/**
* Adds a new facet query
* @param facetQuery the new facet query to be added
*/
public void addFacetQuery(String facetQuery){
this.facetQueries.add(facetQuery);
}
/**
* Returns the facet queries
* @return the facet queries for this query
*/
public List<String> getFacetQueries() {
return facetQueries;
}
/**
* Adds a new facet field
* @param facetField the new facet field to be added
*/
public void addFacetField(FacetFieldConfig facetField){
facetFields.add(facetField);
}
/**
* Gets the facets fields configured
* @return the facet fields for this query
*/
public List<FacetFieldConfig> getFacetFields() {
return facetFields;
}
/**
* Gets the minimum number of values that need to be present before a valid facet value has been found
* @return facetMinCount the minimum number of values to be present for a valid facet
*/
public int getFacetMinCount() {
return facetMinCount;
}
/**
* Set the minimum number of values that need to be present before a valid facet value has been found
* @param facetMinCount the minimum number of values to be present for a valid facet
*/
public void setFacetMinCount(int facetMinCount) {
this.facetMinCount = facetMinCount;
}
/**
* Returns the maximum number of facet values that can be returned for one facet field
* @return how many facet values will be returned
*/
public int getFacetLimit() {
return facetLimit;
}
/**
* Sets maximum number of facet values that can be returned for one facet field
* @param facetLimit how many facet values will be returned
*/
public void setFacetLimit(int facetLimit) {
this.facetLimit = facetLimit;
}
/**
* Gets the facet field offset
* @return the facet field offset
*/
public int getFacetOffset() {
return facetOffset;
}
/**
* Sets the facet field offset, one facet offset will be used for all the facet fields
* @param facetOffset an integer representing the offset
*/
public void setFacetOffset(int facetOffset) {
this.facetOffset = facetOffset;
}
/**
* Get the sort order for the facets
* @return the sort order for the facets
*/
public FACET_SORT getFacetSort() {
return facetSort;
}
/**
* Set the sort order for the facets
* @param facetSort the sort order for the facets
*/
public void setFacetSort(FACET_SORT facetSort) {
this.facetSort = facetSort;
}
public void addSearchField(String field){
this.searchFields.add(field);
}
public List<String> getSearchFields() {
return searchFields;
}
/**
* Returns the misc search properties
* @return a map containing the properties
*/
public Map<String, List<String>> getProperties() {
return properties;
}
/**
* Adds a new search property to the misc search properties
* @param property the name of the property
* @param value the value of the property
*/
public void addProperty(String property, String value){
List<String> toAddList = properties.get(property);
if(toAddList == null)
toAddList = new ArrayList<String>();
toAddList.add(value);
properties.put(property, toAddList);
}
}

View File

@@ -0,0 +1,164 @@
package org.dspace.discovery;
import org.dspace.content.DSpaceObject;
import java.util.*;
/**
* This class represents the result that the discovery search impl returns
*
* @author Kevin Van de Velde (kevin at atmire dot com)
*/
public class DiscoverResult {
private long totalSearchResults;
private int start;
private List<DSpaceObject> dspaceObjects;
private Map<String, List<FacetResult>> facetResults;
/** A map that contains all the documents sougth after, the key is a string representation of the DSpace object */
private Map<String, List<SearchDocument>> searchDocuments;
private int maxResults = -1;
public DiscoverResult() {
dspaceObjects = new ArrayList<DSpaceObject>();
facetResults = new LinkedHashMap<String, List<FacetResult>>();
searchDocuments = new LinkedHashMap<String, List<SearchDocument>>();
}
public void addDSpaceObject(DSpaceObject dso){
this.dspaceObjects.add(dso);
}
public List<DSpaceObject> getDspaceObjects() {
return dspaceObjects;
}
public long getTotalSearchResults() {
return totalSearchResults;
}
public void setTotalSearchResults(long totalSearchResults) {
this.totalSearchResults = totalSearchResults;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getMaxResults() {
return maxResults;
}
public void setMaxResults(int maxResults) {
this.maxResults = maxResults;
}
public void addFacetResult(String facetField, FacetResult ...facetResults){
List<FacetResult> facetValues = this.facetResults.get(facetField);
if(facetValues == null)
{
facetValues = new ArrayList<FacetResult>();
}
facetValues.addAll(Arrays.asList(facetResults));
this.facetResults.put(facetField, facetValues);
}
public Map<String, List<FacetResult>> getFacetResults() {
return facetResults;
}
public List<FacetResult> getFacetResult(String facet){
return facetResults.get(facet) == null ? new ArrayList<FacetResult>() : facetResults.get(facet);
}
public static final class FacetResult{
// TODO: rename storedValue to filterValue
private String asFilterQuery;
private String displayedValue;
private long count;
public FacetResult(String asFilterQuery, String displayedValue, long count) {
this.asFilterQuery = asFilterQuery;
this.displayedValue = displayedValue;
this.count = count;
}
public String getAsFilterQuery() {
return asFilterQuery;
}
public String getDisplayedValue() {
return displayedValue;
}
public long getCount() {
return count;
}
}
public void addSearchDocument(DSpaceObject dso, SearchDocument searchDocument){
String dsoString = SearchDocument.getDspaceObjectStringRepresentation(dso);
List<SearchDocument> docs = searchDocuments.get(dsoString);
if(docs == null){
docs = new ArrayList<SearchDocument>();
}
docs.add(searchDocument);
searchDocuments.put(dsoString, docs);
}
/**
* Returns all the sought after search document values
* @param dso the dspace object we want our search documents for
* @return the search documents list
*/
public List<SearchDocument> getSearchDocument(DSpaceObject dso){
String dsoString = SearchDocument.getDspaceObjectStringRepresentation(dso);
List<SearchDocument> result = searchDocuments.get(dsoString);
if(result == null){
return new ArrayList<SearchDocument>();
}else{
return result;
}
}
/**
* This class contains values from the fields searched for in DiscoveryQuery.java
*/
public static final class SearchDocument{
private Map<String, List<String>> searchFields;
public SearchDocument() {
this.searchFields = new LinkedHashMap<String, List<String>>();
}
public void addSearchField(String field, String ...values){
List<String>searchFieldValues = searchFields.get(field);
if(searchFieldValues == null){
searchFieldValues = new ArrayList<String>();
}
searchFieldValues.addAll(Arrays.asList(values));
searchFields.put(field, searchFieldValues);
}
public Map<String, List<String>> getSearchFields() {
return searchFields;
}
public List<String> getSearchFieldValues(String field){
if(searchFields.get(field) == null)
return new ArrayList<String>();
else
return searchFields.get(field);
}
public static String getDspaceObjectStringRepresentation(DSpaceObject dso){
return dso.getType() + ":" + dso.getID();
}
}
}

View File

@@ -0,0 +1,36 @@
package org.dspace.discovery;
/**
* Class contains all the data that can be configured for a facet field
*
* @author Kevin Van de Velde (kevin at atmire dot com)
*/
public class FacetFieldConfig {
private String field;
private boolean isDate;
/* The facet prefix, all facet values will have to start with the given prefix */
private String prefix;
public FacetFieldConfig(String field, boolean date) {
this.field = field;
isDate = date;
}
public FacetFieldConfig(String field, boolean date, String prefix) {
this.prefix = prefix;
this.field = field;
isDate = date;
}
public String getField() {
return field;
}
public boolean isDate() {
return isDate;
}
public String getPrefix() {
return prefix;
}
}

View File

@@ -34,7 +34,6 @@ public class IndexClient {
* @param args the command-line arguments, none used
* @throws java.io.IOException
* @throws java.sql.SQLException
* @throws org.apache.solr.client.solrj.SolrServerException
*
*/
public static void main(String[] args) throws SQLException, IOException, SearchServiceException {
@@ -78,7 +77,7 @@ public class IndexClient {
"print this help message").create("h"));
options.addOption(OptionBuilder.isRequired(false).withDescription(
"optimize search solr core").create("o"));
"optimize search core").create("o"));
try {
line = new PosixParser().parse(options, args);

View File

@@ -7,15 +7,14 @@
*/
package org.dspace.discovery;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.dspace.content.DSpaceObject;
import org.dspace.core.Context;
import java.sql.SQLException;
import java.util.List;
/**
* Search interface that discovery to search in solr
* Search interface that discovery uses
*
* @author Kevin Van de Velde (kevin at atmire dot com)
* @author Mark Diggory (markd at atmire dot com)
@@ -23,9 +22,33 @@ import java.util.List;
*/
public interface SearchService {
QueryResponse search(SolrQuery query) throws SearchServiceException;
DiscoverResult search(Context context, DiscoverQuery query) throws SearchServiceException;
DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery query) throws SearchServiceException;
String searchJSON(DiscoverQuery query, String jsonIdentifier) throws SearchServiceException;
List<DSpaceObject> search(Context context, String query, int offset, int max, String... filterquery);
List<DSpaceObject> search(Context context, String query, String orderfield, boolean ascending, int offset, int max, String... filterquery);
/**
* Transforms the given string into a filter query
* @param context the DSpace context
* @param filterQuery the filter query
* @return a filter query object
* @throws java.sql.SQLException ...
*/
DiscoverFilterQuery toFilterQuery(Context context, String filterQuery) throws SQLException;
/**
* Transforms the given string field and value into a filter query
* @param context the DSpace context
* @param field the field of the filter query
* @param value the filter query value
* @return a filter query
* @throws SQLException ...
*/
DiscoverFilterQuery toFilterQuery(Context context, String field, String value) throws SQLException;
}

View File

@@ -8,7 +8,7 @@
package org.dspace.discovery;
/**
* Exception used by discovery when solr exceptions occur
* Exception used by discovery when discovery search exceptions occur
*
* @author Kevin Van de Velde (kevin at atmire dot com)
* @author Mark Diggory (markd at atmire dot com)

View File

@@ -9,16 +9,12 @@ package org.dspace.discovery;
import org.apache.commons.collections.ExtendedProperties;
import org.apache.log4j.Logger;
import org.apache.solr.common.SolrDocument;
import org.dspace.content.DSpaceObject;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context;
import org.dspace.handle.HandleManager;
import org.dspace.utils.DSpace;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.*;
/**
@@ -34,18 +30,24 @@ public class SearchUtils {
private static ExtendedProperties props = null;
private static Map<String, SolrFacetConfig[]> solrFacets = new HashMap<String, SolrFacetConfig[]>();
private static Map<String, FacetFieldConfig[]> fieldFacets = new HashMap<String, FacetFieldConfig[]>();
private static List<String> allFacets = new ArrayList<String>();
private static List<String> searchFilters = new ArrayList<String>();
private static List<String> searchFiltersFullAutocomplete = new ArrayList<String>();
private static List<String> sortFields = new ArrayList<String>();
private static List<String> dateIndexableFields = new ArrayList<String>();
public static final String FILTER_SEPARATOR = "|||";
/** Cached search service **/
private static SearchService searchService;
static {
log.debug("loading configuration");
@@ -61,7 +63,7 @@ public class SearchUtils {
} else {
InputStream is = null;
try {
is = SolrServiceImpl.class.getResourceAsStream("dspace-solr-search.cfg");
is = SearchUtils.class.getResourceAsStream("dspace-solr-search.cfg");
ExtendedProperties defaults = new ExtendedProperties();
defaults.load(is);
props.combine(defaults);
@@ -87,30 +89,39 @@ public class SearchUtils {
log.info("loading scope, " + propName);
allFacets.addAll(Arrays.asList(propVals));
List<SolrFacetConfig> facets = new ArrayList<SolrFacetConfig>();
List<FacetFieldConfig> facets = new ArrayList<FacetFieldConfig>();
for (String propVal : propVals) {
if (propVal.endsWith("_dt") || propVal.endsWith(".year")) {
facets.add(new SolrFacetConfig(propVal.replace("_dt", ".year"), true));
facets.add(new FacetFieldConfig(propVal.replace("_dt", ".year"), true));
log.info("value, " + propVal);
} else {
facets.add(new SolrFacetConfig(propVal + "_filter", false));
facets.add(new FacetFieldConfig(propVal + "_filter", false));
log.info("value, " + propVal);
}
}
//All the values are split into date & facetfields, so now store em
solrFacets.put(propName.replace("solr.facets.", ""), facets.toArray(new SolrFacetConfig[facets.size()]));
fieldFacets.put(propName.replace("solr.facets.", ""), facets.toArray(new FacetFieldConfig[facets.size()]));
log.info("solrFacets size: " + solrFacets.size());
log.info("fieldFacets size: " + fieldFacets.size());
}
}
String[] filterFieldsProps = SearchUtils.getConfig().getStringArray("solr.search.filters");
if (filterFieldsProps != null) {
searchFilters.addAll(Arrays.asList(filterFieldsProps));
for (String filterProp : filterFieldsProps) {
if(filterProp.endsWith(":full")){
String field = filterProp.substring(0, filterProp.lastIndexOf(":"));
searchFiltersFullAutocomplete.add(field);
searchFilters.add(field);
}else{
searchFilters.add(filterProp);
}
}
}
String[] sortFieldProps = SearchUtils.getConfig().getStringArray("solr.search.sort");
@@ -131,8 +142,8 @@ public class SearchUtils {
return props;
}
public static SolrFacetConfig[] getFacetsForType(String type) {
return solrFacets.get(type);
public static FacetFieldConfig[] getFacetsForType(String type) {
return fieldFacets.get(type);
}
public static List<String> getAllFacets() {
@@ -143,24 +154,14 @@ public class SearchUtils {
return searchFilters;
}
public static boolean isNonTokenizedSearchFilter(String field){
return searchFiltersFullAutocomplete.contains(field);
}
public static List<String> getSortFields() {
return sortFields;
}
public static DSpaceObject findDSpaceObject(Context context, SolrDocument doc) throws SQLException {
Integer type = (Integer) doc.getFirstValue("search.resourcetype");
Integer id = (Integer) doc.getFirstValue("search.resourceid");
String handle = (String) doc.getFirstValue("handle");
if (type != null && id != null) {
return DSpaceObject.find(context, type, id);
} else if (handle != null) {
return HandleManager.resolveToObject(context, handle);
}
return null;
}
public static String[] getDefaultFilters(String scope) {
@@ -192,37 +193,14 @@ public class SearchUtils {
return dateIndexableFields;
}
public static String getFilterQueryDisplay(String filterQuery){
String separator = SearchUtils.getConfig().getString("solr.facets.split.char", SearchUtils.FILTER_SEPARATOR);
//Escape any regex chars
separator = java.util.regex.Pattern.quote(separator);
String[] fqParts = filterQuery.split(separator);
String result = "";
int start = fqParts.length / 2;
for(int i = start; i < fqParts.length; i++){
result += fqParts[i];
}
return result;
}
public static class SolrFacetConfig {
private String facetField;
private boolean isDate;
public SolrFacetConfig(String facetField, boolean date) {
this.facetField = facetField;
isDate = date;
}
public String getFacetField() {
return facetField;
}
public boolean isDate() {
return isDate;
public static SearchService getSearchService()
{
if(searchService == null){
DSpace dspace = new DSpace();
org.dspace.kernel.ServiceManager manager = dspace.getServiceManager() ;
searchService = manager.getServiceByName(SearchService.class.getName(),SearchService.class);
}
return searchService;
}
}

View File

@@ -7,17 +7,21 @@
*/
package org.dspace.discovery;
import org.apache.commons.collections.ExtendedProperties;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.FacetParams;
import org.dspace.content.*;
import org.dspace.content.Collection;
import org.dspace.core.ConfigurationManager;
@@ -32,6 +36,7 @@ import org.springframework.beans.factory.annotation.Required;
import org.springframework.stereotype.Service;
import java.io.*;
import java.net.URLEncoder;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@@ -665,6 +670,8 @@ public class SolrServiceImpl implements SearchService, IndexingService {
continue;
}
indexItemFieldCustom(doc, item, field, value);
//Add the field to all for autocomplete so our autocomplete works for all fields
doc.addField("all_ac", value);
@@ -696,6 +703,9 @@ public class SolrServiceImpl implements SearchService, IndexingService {
if(SearchUtils.getSearchFilters().contains(field) || SearchUtils.getSearchFilters().contains(unqualifiedField + "." + Item.ANY)){
//Add a dynamic fields for autocomplete in search
doc.addField(field + "_ac", value);
if(SearchUtils.isNonTokenizedSearchFilter(field) || SearchUtils.isNonTokenizedSearchFilter(unqualifiedField + "." + Item.ANY)){
doc.addField(field + "_ac.full", value);
}
}
if(SearchUtils.getAllFacets().contains(field) || SearchUtils.getAllFacets().contains(unqualifiedField + "." + Item.ANY)){
@@ -814,6 +824,18 @@ public class SolrServiceImpl implements SearchService, IndexingService {
}
}
/**
* Method that can be overriden to handle special metadata indexing tasks
* @param doc the solr input document
* @param item the DSpace item that is beeing indexed
* @param field the metadata field which we are indexing
* @param value the metadata value which we are indexing
* @return whether or not to continue indexing the metadata value
*/
public boolean indexItemFieldCustom(SolrInputDocument doc, Item item, String field, String value) {
return true;
}
/**
* Create Lucene document with all the shared fields initialized.
*
@@ -931,16 +953,319 @@ public class SolrServiceImpl implements SearchService, IndexingService {
}
//******** SearchService implementation
public QueryResponse search(SolrQuery query) throws SearchServiceException {
public DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery discoveryQuery) throws SearchServiceException {
if(dso != null){
if (dso instanceof Community) {
discoveryQuery.addFilterQueries("location:m" + dso.getID());
} else if (dso instanceof Collection) {
discoveryQuery.addFilterQueries("location:l" + dso.getID());
} else if (dso instanceof Item){
discoveryQuery.addFilterQueries("handle:" + dso.getHandle());
}
}
return search(context, discoveryQuery);
}
public DiscoverResult search(Context context, DiscoverQuery discoveryQuery) throws SearchServiceException {
try {
return getSolr().query(query);
SolrQuery solrQuery = new SolrQuery();
String query = "*:*";
if(discoveryQuery.getQuery() != null){
query = discoveryQuery.getQuery();
}
solrQuery.setQuery(query);
for (int i = 0; i < discoveryQuery.getFilterQueries().size(); i++) {
String filterQuery = discoveryQuery.getFilterQueries().get(i);
solrQuery.addFilterQuery(prepareFilterQuery(filterQuery));
}
if(discoveryQuery.getDSpaceObjectFilter() != -1){
solrQuery.addFilterQuery("search.resourcetype:" + discoveryQuery.getDSpaceObjectFilter());
}
for (int i = 0; i < discoveryQuery.getFieldPresentQueries().size(); i++) {
String filterQuery = discoveryQuery.getFieldPresentQueries().get(i);
solrQuery.addFilterQuery(filterQuery + ":[* TO *]");
}
if(discoveryQuery.getStart() != -1){
solrQuery.setStart(discoveryQuery.getStart());
}
if(discoveryQuery.getMaxResults() != -1){
solrQuery.setRows(discoveryQuery.getMaxResults());
}
if(discoveryQuery.getSortField() != null){
SolrQuery.ORDER order = SolrQuery.ORDER.asc;
if(discoveryQuery.getSortOrder().equals(DiscoverQuery.SORT_ORDER.desc))
order = SolrQuery.ORDER.desc;
solrQuery.addSortField(discoveryQuery.getSortField(), order);
}
for(String property : discoveryQuery.getProperties().keySet()){
List<String> values = discoveryQuery.getProperties().get(property);
solrQuery.add(property, values.toArray(new String[values.size()]));
}
List<FacetFieldConfig> facetFields = discoveryQuery.getFacetFields();
if(0 < facetFields.size()){
//Only add facet information if there are any facets
for (FacetFieldConfig facetFieldConfig : facetFields) {
solrQuery.addFacetField(facetFieldConfig.getField());
if(facetFieldConfig.getPrefix() != null){
solrQuery.setFacetPrefix(facetFieldConfig.getField(), facetFieldConfig.getPrefix());
}
}
List<String> facetQueries = discoveryQuery.getFacetQueries();
for (String facetQuery : facetQueries) {
solrQuery.addFacetQuery(facetQuery);
}
if(discoveryQuery.getFacetLimit() != -1){
solrQuery.setFacetLimit(discoveryQuery.getFacetLimit());
}
if(discoveryQuery.getFacetMinCount() != -1){
solrQuery.setFacetMinCount(discoveryQuery.getFacetMinCount());
}
solrQuery.setParam(FacetParams.FACET_OFFSET, String.valueOf(discoveryQuery.getFacetOffset()));
if(discoveryQuery.getFacetSort() == DiscoverQuery.FACET_SORT.COUNT){
solrQuery.setFacetSort(FacetParams.FACET_SORT_COUNT);
} else {
solrQuery.setFacetSort(FacetParams.FACET_SORT_INDEX);
}
}
QueryResponse queryResponse = getSolr().query(solrQuery);
return retrieveResult(context, discoveryQuery, queryResponse);
} catch (Exception e) {
throw new org.dspace.discovery.SearchServiceException(e.getMessage(),e);
}
}
public String searchJSON(DiscoverQuery query, String jsonIdentifier) throws SearchServiceException {
Map<String, String> params = new HashMap<String, String>();
String solrRequestUrl = solr.getBaseURL() + "/select";
//Add our default parameters
params.put(CommonParams.ROWS, "0");
params.put(CommonParams.WT, "json");
//We uwe json as out output type
params.put("json.nl", "map");
params.put("json.wrf", jsonIdentifier);
params.put(FacetParams.FACET, Boolean.TRUE.toString());
//Generate our json out of the given params
try
{
params.put(CommonParams.Q, URLEncoder.encode(query.getQuery(), org.dspace.constants.Constants.DEFAULT_ENCODING));
}
catch (UnsupportedEncodingException uee)
{
//Should never occur
return null;
}
if(query.getFacetSort() == DiscoverQuery.FACET_SORT.COUNT){
params.put(FacetParams.FACET_SORT, FacetParams.FACET_SORT_COUNT);
} else {
params.put(FacetParams.FACET_SORT, FacetParams.FACET_SORT_INDEX);
}
params.put(FacetParams.FACET_LIMIT, String.valueOf(query.getFacetLimit()));
params.put(FacetParams.FACET_MINCOUNT, String.valueOf(query.getFacetMinCount()));
solrRequestUrl = generateURL(solrRequestUrl, params);
if (query.getFacetFields() != null || query.getFilterQueries() != null) {
StringBuilder urlBuilder = new StringBuilder(solrRequestUrl);
if(query.getFacetFields() != null){
//Add our facet fields
for (FacetFieldConfig facetFieldConfig : query.getFacetFields()) {
urlBuilder.append("&").append(FacetParams.FACET_FIELD).append("=");
//This class can only be used for autocomplete facet fields
if(!facetFieldConfig.getField().endsWith(".year") && !facetFieldConfig.getField().endsWith("_ac"))
{
try {
String field;
if(SearchUtils.isNonTokenizedSearchFilter(facetFieldConfig.getField())){
field = facetFieldConfig.getField() + "_ac.full";
}else{
field = facetFieldConfig.getField() + "_ac";
}
urlBuilder.append(URLEncoder.encode(field, org.dspace.constants.Constants.DEFAULT_ENCODING));
} catch (UnsupportedEncodingException e) {
//Ignore this
}
}
else
{
try {
urlBuilder.append(URLEncoder.encode(facetFieldConfig.getField(), org.dspace.constants.Constants.DEFAULT_ENCODING));
} catch (UnsupportedEncodingException e) {
//Ignore this
}
}
}
}
if(query.getFilterQueries() != null){
for (String filterQuery : query.getFilterQueries()) {
try {
urlBuilder.append("&").append(CommonParams.FQ).append("=").append(URLEncoder.encode(filterQuery, org.dspace.constants.Constants.DEFAULT_ENCODING));
} catch (UnsupportedEncodingException e) {
//Ignore this
}
}
}
solrRequestUrl = urlBuilder.toString();
}
try {
GetMethod get = new GetMethod(solrRequestUrl);
new HttpClient().executeMethod(get);
return get.getResponseBodyAsString();
} catch (Exception e) {
log.error("Error while getting json solr result for discovery search recommendation", e);
e.printStackTrace();
}
return null;
}
private String generateURL(String baseURL, Map<String, String> parameters)
{
boolean first = true;
for (String key : parameters.keySet())
{
if (first)
{
baseURL += "?";
first = false;
}
else
{
baseURL += "&";
}
baseURL += key + "=" + parameters.get(key);
}
return baseURL;
}
private String prepareFilterQuery(String filterQuery) {
//Ensure that range queries or specified field queries do not get a wildcard at the end
if(!filterQuery.matches(".*\\:\\[.* TO .*\\](?![a-z 0-9]).*") && !filterQuery.matches(".*:\".*\"$") && !filterQuery.endsWith("*")){
filterQuery = filterQuery + " OR " + filterQuery + "*";
}
return filterQuery;
}
private DiscoverResult retrieveResult(Context context, DiscoverQuery query, QueryResponse solrQueryResponse) throws SQLException {
DiscoverResult result = new DiscoverResult();
if(solrQueryResponse != null){
result.setStart(query.getStart());
result.setMaxResults(query.getMaxResults());
result.setTotalSearchResults(solrQueryResponse.getResults().getNumFound());
List<String> searchFields = query.getSearchFields();
for (SolrDocument doc : solrQueryResponse.getResults()) {
DSpaceObject dso = findDSpaceObject(context, doc);
if(dso != null){
result.addDSpaceObject(dso);
} else {
//TODO: Log this !
continue;
}
DiscoverResult.SearchDocument resultDoc = new DiscoverResult.SearchDocument();
//Add information about our search fields
for (String field : searchFields){
List<String> valuesAsString = new ArrayList<String>();
for (Object o : doc.getFieldValues(field)) {
valuesAsString.add(String.valueOf(o));
}
resultDoc.addSearchField(field, valuesAsString.toArray(new String[valuesAsString.size()]));
}
result.addSearchDocument(dso, resultDoc);
}
//Resolve our facet field values
List<FacetField> facetFields = solrQueryResponse.getFacetFields();
if(facetFields != null){
for (FacetField facetField : facetFields) {
List<FacetField.Count> facetValues = facetField.getValues();
if(facetValues != null){
for (FacetField.Count facetValue : facetValues) {
String displayedValue = transformDisplayedValue(context, facetField.getName(), facetValue.getName());
result.addFacetResult(facetField.getName(), new DiscoverResult.FacetResult(facetValue.getAsFilterQuery(), displayedValue, facetValue.getCount()));
}
}
}
}
if(solrQueryResponse.getFacetQuery() != null){
//TODO: do not sort when not a date, just retrieve the facets in the order they where requested !
//At the moment facet queries are only used for dates so we need to sort our results
TreeMap<String, Integer> sortedFacetQueries = new TreeMap<String, Integer>(solrQueryResponse.getFacetQuery());
for(String facetQuery : sortedFacetQueries.descendingKeySet()){
//TODO: do not assume this, people may want to use it for other ends, use a regex to make sure
//We have a facet query, the values looks something like: dateissued.year:[1990 TO 2000] AND -2000
//Prepare the string from {facet.field.name}:[startyear TO endyear] to startyear - endyear
String facetField = facetQuery.substring(0, facetQuery.indexOf(":"));
String name = facetQuery.substring(facetQuery.indexOf('[') + 1);
name = name.substring(0, name.lastIndexOf(']')).replaceAll("TO", "-");
Integer count = sortedFacetQueries.get(facetQuery);
//No need to show empty years
if(0 < count){
result.addFacetResult(facetField, new DiscoverResult.FacetResult(facetQuery, name, count));
}
}
}
}
return result;
}
private static DSpaceObject findDSpaceObject(Context context, SolrDocument doc) throws SQLException {
Integer type = (Integer) doc.getFirstValue("search.resourcetype");
Integer id = (Integer) doc.getFirstValue("search.resourceid");
String handle = (String) doc.getFirstValue("handle");
if (type != null && id != null) {
return DSpaceObject.find(context, type, id);
} else if (handle != null) {
return HandleManager.resolveToObject(context, handle);
}
return null;
}
/** Simple means to return the search result as an InputStream */
public java.io.InputStream searchAsInputStream(SolrQuery query) throws SearchServiceException, java.io.IOException {
public java.io.InputStream searchAsInputStream(DiscoverQuery query) throws SearchServiceException, java.io.IOException {
try {
org.apache.commons.httpclient.methods.GetMethod method =
new org.apache.commons.httpclient.methods.GetMethod(getSolr().getHttpClient().getHostConfiguration().getHostURL() + "");
@@ -998,4 +1323,70 @@ public class SolrServiceImpl implements SearchService, IndexingService {
}
}
public DiscoverFilterQuery toFilterQuery(Context context, String filterQuery) throws SQLException {
DiscoverFilterQuery result = new DiscoverFilterQuery();
//TODO: what if user enters something with a ":" in it
String field = filterQuery;
String value = filterQuery;
if(filterQuery.contains(":"))
{
field = filterQuery.substring(0, filterQuery.indexOf(":"));
value = filterQuery.substring(filterQuery.indexOf(":") + 1, filterQuery.length());
}else{
//We have got no field, so we are using everything
field = "*";
}
value = value.replace("\\", "");
if("*".equals(field))
{
field = "all";
}
if(filterQuery.startsWith("*:") || filterQuery.startsWith(":"))
{
filterQuery = filterQuery.substring(filterQuery.indexOf(":") + 1, filterQuery.length());
}
value = transformDisplayedValue(context, field, value);
result.setField(field);
result.setFilterQuery(filterQuery);
result.setDisplayedValue(value);
return result;
}
public DiscoverFilterQuery toFilterQuery(Context context, String field, String value) throws SQLException{
DiscoverFilterQuery result = new DiscoverFilterQuery();
result.setField(field);
result.setDisplayedValue(transformDisplayedValue(context, field, value));
// TODO: solr escape of value ?
result.setFilterQuery((field == null || field.equals("") ? "" : field + ":") + "\"" + value + "\"");
return result;
}
private String transformDisplayedValue(Context context, String field, String value) throws SQLException {
if(field.equals("location.comm") || field.equals("location.coll")){
value = locationToName(context, field, value);
}else
if(field.endsWith("_filter")){
//We have a filter make sure we split !
String separator = SearchUtils.getConfig().getString("solr.facets.split.char", SearchUtils.FILTER_SEPARATOR);
//Escape any regex chars
separator = java.util.regex.Pattern.quote(separator);
String[] fqParts = value.split(separator);
StringBuffer valueBuffer = new StringBuffer();
int start = fqParts.length / 2;
for(int i = start; i < fqParts.length; i++){
valueBuffer.append(fqParts[i]);
}
value = valueBuffer.toString();
}
return value;
}
}

View File

@@ -27,4 +27,4 @@
<bean class="org.dspace.discovery.SolrServiceImpl" id="org.dspace.discovery.SearchService"/>
<alias name="org.dspace.discovery.SearchService" alias="org.dspace.discovery.IndexingService"/>
</beans>
</beans>

View File

@@ -0,0 +1,144 @@
package org.dspace.app.xmlui.aspect.discovery;
import org.apache.cocoon.caching.CacheableProcessingComponent;
import org.apache.cocoon.util.HashUtil;
import org.apache.excalibur.source.SourceValidity;
import org.apache.log4j.Logger;
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
import org.dspace.app.xmlui.utils.DSpaceValidity;
import org.dspace.app.xmlui.utils.HandleUtil;
import org.dspace.content.DSpaceObject;
import org.dspace.core.Constants;
import org.dspace.discovery.*;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;
/**
* An abstract class containing the shared methods which all recent submission transformers use
*
* @author Kevin Van de Velde (kevin at atmire dot com)
*/
public abstract class AbstractRecentSubmissionTransformer extends AbstractDSpaceTransformer implements CacheableProcessingComponent {
private static final Logger log = Logger.getLogger(AbstractRecentSubmissionTransformer.class);
/**
* Cached query results
*/
protected DiscoverResult queryResults;
/** Cached validity object */
private SourceValidity validity;
/**
* Generate the unique caching key.
* This key must be unique inside the space of this component.
*/
@Override
public Serializable getKey() {
try
{
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
if (dso == null)
{
return "0";
}
return HashUtil.hash(dso.getHandle());
}
catch (SQLException sqle)
{
// Ignore all errors and just return that the component is not
// cachable.
return "0";
}
}
/**
* Generate the cache validity object.
*
* The validity object all recently submitted items.
* This does not include the community / collection
* hierarchy, when this changes they will not be reflected in the cache.
*/
public SourceValidity getValidity()
{
if (this.validity == null)
{
try
{
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
DSpaceValidity validity = new DSpaceValidity();
// Add the actual collection;
validity.add(dso);
getRecentlySubmittedItems(dso);
if(queryResults != null){
List<DSpaceObject> resultingObjects = queryResults.getDspaceObjects();
for(DSpaceObject resultObject : resultingObjects){
validity.add(resultObject);
}
validity.add("numFound:" + resultingObjects.size());
}
this.validity = validity.complete();
}
catch (Exception e)
{
// Just ignore all errors and return an invalid cache.
}
}
return this.validity;
}
protected abstract String getView();
/**
* Retrieves the recent submitted items of the given scope
*
* @param dso the DSpace object can either be null (indicating home page), a collection or a community
*/
protected void getRecentlySubmittedItems(DSpaceObject dso) {
if(queryResults != null)
{
return; // queryResults;
}
try {
DiscoverQuery queryArgs = new DiscoverQuery();
queryArgs.addFilterQueries(SearchUtils.getDefaultFilters(getView()));
queryArgs.setDSpaceObjectFilter(Constants.ITEM);
queryArgs.setMaxResults(SearchUtils.getConfig().getInt("solr.recent-submissions.size", 5));
String sortField = SearchUtils.getConfig().getString("recent.submissions.sort-option");
if(sortField != null){
queryArgs.setSortField(
sortField,
DiscoverQuery.SORT_ORDER.desc
);
}
SearchService service = SearchUtils.getSearchService();
queryResults = service.search(context, dso, queryArgs);
}catch (SearchServiceException se){
log.error("Caught SearchServiceException while retrieving recent submission for: " + getView(), se);
}
}
@Override
public void recycle() {
queryResults = null;
validity = null;
super.recycle();
}
}

View File

@@ -7,13 +7,13 @@
*/
package org.dspace.app.xmlui.aspect.discovery;
import org.apache.cocoon.caching.CacheableProcessingComponent;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.util.HashUtil;
import org.apache.excalibur.source.SourceValidity;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
import org.dspace.app.xmlui.utils.DSpaceValidity;
import org.dspace.app.xmlui.utils.HandleUtil;
import org.dspace.app.xmlui.utils.UIException;
@@ -26,6 +26,7 @@ import org.dspace.content.Collection;
import org.dspace.content.Item;
import org.dspace.core.LogManager;
import org.dspace.discovery.*;
import org.dspace.handle.HandleManager;
import org.dspace.sort.SortOption;
import org.xml.sax.SAXException;
@@ -46,7 +47,7 @@ import java.util.List;
* @author Mark Diggory (markd at atmire dot com)
* @author Ben Bosman (ben at atmire dot com)
*/
public abstract class AbstractSearch extends AbstractFiltersTransformer {
public abstract class AbstractSearch extends AbstractDSpaceTransformer implements CacheableProcessingComponent{
private static final Logger log = Logger.getLogger(AbstractSearch.class);
@@ -86,6 +87,16 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
private static final Message T_rpp = message("xmlui.ArtifactBrowser.AbstractSearch.rpp");
/**
* Cached query results
*/
protected DiscoverResult queryResults;
/**
* Cached query arguments
*/
protected DiscoverQuery queryArgs;
/**
* The options for results per page
*/
@@ -147,15 +158,24 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
performSearch(scope);
SolrDocumentList results = this.queryResults.getResults();
List<DSpaceObject> results = this.queryResults.getDspaceObjects();
if (results != null) {
validity.add("total:"+results.getNumFound());
validity.add("start:"+results.getStart());
validity.add("total:"+this.queryResults.getTotalSearchResults());
validity.add("start:"+this.queryResults.getStart());
validity.add("size:" + results.size());
for (SolrDocument result : results) {
validity.add(result.toString());
for (DSpaceObject dso : results) {
validity.add(dso);
}
}
Map<String, List<DiscoverResult.FacetResult>> facetResults = this.queryResults.getFacetResults();
for(String facetField : facetResults.keySet()){
List<DiscoverResult.FacetResult> facetValues = facetResults.get(facetField);
for (DiscoverResult.FacetResult facetResult : facetValues)
{
validity.add(facetResult.getAsFilterQuery() + facetResult.getCount());
}
}
@@ -191,7 +211,7 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
throws IOException, SQLException, WingException, SearchServiceException {
try {
if (queryResults == null || queryResults.getResults() == null) {
if (queryResults == null) {
DSpaceObject scope = getScope();
this.performSearch(scope);
@@ -208,7 +228,7 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
if (queryResults != null) {
search.addPara("result-query", "result-query")
.addContent(T_result_query.parameterize(getQuery(), queryResults.getResults().getNumFound()));
.addContent(T_result_query.parameterize(getQuery(), queryResults.getTotalSearchResults()));
}
Division results = search.addDivision("search-results", "primary");
@@ -227,20 +247,18 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
results.setHead(T_head1_none);
}
if (queryResults != null &&
queryResults.getResults().getNumFound() > 0) {
SolrDocumentList solrResults = queryResults.getResults();
if (queryResults != null && 0< queryResults.getDspaceObjects().size())
{
// Pagination variables.
int itemsTotal = (int) solrResults.getNumFound();
int firstItemIndex = (int) solrResults.getStart() + 1;
int lastItemIndex = (int) solrResults.getStart() + solrResults.size();
int itemsTotal = (int) queryResults.getTotalSearchResults();
int firstItemIndex = (int) this.queryResults.getStart() + 1;
int lastItemIndex = (int) this.queryResults.getStart() + queryResults.getDspaceObjects().size();
//if (itemsTotal < lastItemIndex)
// lastItemIndex = itemsTotal;
int currentPage = (int) (solrResults.getStart() / this.queryArgs.getRows()) + 1;
int pagesTotal = (int) ((solrResults.getNumFound() - 1) / this.queryArgs.getRows()) + 1;
int currentPage = (int) (this.queryResults.getStart() / this.queryResults.getMaxResults()) + 1;
int pagesTotal = (int) ((this.queryResults.getTotalSearchResults() - 1) / this.queryResults.getMaxResults()) + 1;
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("page", "{pageNum}");
String pageURLMask = generateURL(parameters);
@@ -261,20 +279,16 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
// Look for any communities or collections in the mix
ReferenceSet referenceSet = null;
for (SolrDocument doc : solrResults) {
DSpaceObject resultDSO =
SearchUtils.findDSpaceObject(context, doc);
if (resultDSO instanceof Community
|| resultDSO instanceof Collection) {
for (DSpaceObject resultDso : queryResults.getDspaceObjects())
{
if (resultDso instanceof Community || resultDso instanceof Collection) {
if (referenceSet == null) {
referenceSet = results.addReferenceSet("search-results-repository",
ReferenceSet.TYPE_SUMMARY_LIST, null, "repository-search-results");
// Set a heading showing that we will be listing containers that matched:
referenceSet.setHead(T_head2);
}
referenceSet.addReference(resultDSO);
referenceSet.addReference(resultDso);
}
}
@@ -284,12 +298,11 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
ReferenceSet.TYPE_SUMMARY_LIST, null, "repository-search-results");
for (SolrDocument doc : solrResults) {
DSpaceObject resultDSO = SearchUtils.findDSpaceObject(context, doc);
if (resultDSO instanceof Item) {
referenceSet.addReference(resultDSO);
for (DSpaceObject resultDso : queryResults.getDspaceObjects())
{
if (resultDso instanceof Item)
{
referenceSet.addReference(resultDso);
}
}
@@ -374,14 +387,7 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
List<String> filterQueries = new ArrayList<String>();
if (scope instanceof Community) {
filterQueries.add("location:m" + scope.getID());
} else if (scope instanceof Collection) {
filterQueries.add("location:l" + scope.getID());
}
String[] fqs = getSolrFilterQueries();
String[] fqs = getFilterQueries();
if (fqs != null)
{
@@ -389,14 +395,16 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
}
queryArgs = this.prepareDefaultFilters("search", filterQueries.toArray(new String[filterQueries.size()]));
this.queryArgs = new DiscoverQuery();
queryArgs.addFilterQueries(SearchUtils.getDefaultFilters(getView()));
if (filterQueries.size() > 0) {
queryArgs.addFilterQuery(filterQueries.toArray(new String[filterQueries.size()]));
queryArgs.addFilterQueries(filterQueries.toArray(new String[filterQueries.size()]));
}
queryArgs.setRows(getParameterRpp());
queryArgs.setMaxResults(getParameterRpp());
String sortBy = ObjectModelHelper.getRequest(objectModel).getParameter("sort_by");
@@ -411,14 +419,14 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
if (sortBy != null) {
if (sortOrder == null || sortOrder.equals("DESC"))
{
queryArgs.addSortField(sortBy, SolrQuery.ORDER.desc);
queryArgs.setSortField(sortBy, DiscoverQuery.SORT_ORDER.desc);
}
else
{
queryArgs.addSortField(sortBy, SolrQuery.ORDER.asc);
queryArgs.setSortField(sortBy, DiscoverQuery.SORT_ORDER.asc);
}
} else {
queryArgs.addSortField("score", SolrQuery.ORDER.asc);
queryArgs.setSortField("score", DiscoverQuery.SORT_ORDER.asc);
}
@@ -428,26 +436,26 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
// Enable groupBy collapsing if designated
if (groupBy != null && !groupBy.equalsIgnoreCase("none")) {
/** Construct a Collapse Field Query */
queryArgs.add("collapse.field", groupBy);
queryArgs.add("collapse.threshold", "1");
queryArgs.add("collapse.includeCollapsedDocs.fl", "handle");
queryArgs.add("collapse.facet", "before");
queryArgs.addProperty("collapse.field", groupBy);
queryArgs.addProperty("collapse.threshold", "1");
queryArgs.addProperty("collapse.includeCollapsedDocs.fl", "handle");
queryArgs.addProperty("collapse.facet", "before");
//queryArgs.a type:Article^2
// TODO: This is a hack to get Publications (Articles) to always be at the top of Groups.
// TODO: I think the can be more transparently done in the solr solrconfig.xml with DISMAX and boosting
/** sort in groups to get publications to top */
queryArgs.addSortField("dc.type", SolrQuery.ORDER.asc);
queryArgs.setSortField("dc.type", DiscoverQuery.SORT_ORDER.asc);
}
queryArgs.setQuery(query != null && !query.trim().equals("") ? query : "*:*");
queryArgs.setQuery(query != null && !query.trim().equals("") ? query : null);
if (page > 1)
{
queryArgs.setStart((page - 1) * queryArgs.getRows());
queryArgs.setStart((page - 1) * queryResults.getMaxResults());
}
else
{
@@ -509,7 +517,7 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
}
*/
this.queryResults = getSearchService().search(queryArgs);
this.queryResults = SearchUtils.getSearchService().search(context, scope, queryArgs);
}
@@ -532,7 +540,7 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
* This method returns more expanded filter queries then the getParameterFilterQueries
* @return an array containing the filter queries
*/
protected String[] getSolrFilterQueries() {
protected String[] getFilterQueries() {
try {
return ObjectModelHelper.getRequest(objectModel).getParameterValues("fq");
}
@@ -628,6 +636,8 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
* Recycle
*/
public void recycle() {
this.queryArgs = null;
this.queryResults = null;
this.validity = null;
super.recycle();
}
@@ -635,11 +645,6 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
protected void buildSearchControls(Division div)
throws WingException {
Table controlsTable = div.addTable("search-controls", 1, 3);
//Table controlsTable = div.addTable("search-controls", 1, 4);
Row controlsRow = controlsTable.addRow(Row.ROLE_DATA);
@@ -710,6 +715,33 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
//}
}
/**
* Determine the current scope. This may be derived from the current url
* handle if present or the scope parameter is given. If no scope is
* specified then null is returned.
*
* @return The current scope.
*/
private DSpaceObject getScope() throws SQLException {
Request request = ObjectModelHelper.getRequest(objectModel);
String scopeString = request.getParameter("scope");
// Are we in a community or collection?
DSpaceObject dso;
if (scopeString == null || "".equals(scopeString))
{
// get the search scope from the url handle
dso = HandleUtil.obtainHandle(objectModel);
}
else
{
// Get the search scope from the location parameter
dso = HandleManager.resolveToObject(context, scopeString);
}
return dso;
}
protected void logSearch() {
int countCommunities = 0;
int countCollections = 0;
@@ -750,7 +782,9 @@ public abstract class AbstractSearch extends AbstractFiltersTransformer {
}
log.info(LogManager.getHeader(context, "search", logInfo + "query=\""
+ queryArgs.getQuery() + "\",results=(" + countCommunities + ","
+ (queryArgs == null ? "" : queryArgs.getQuery()) + "\",results=(" + countCommunities + ","
+ countCollections + "," + countItems + ")"));
}
public abstract String getView();
}

View File

@@ -26,13 +26,8 @@ import org.apache.cocoon.util.HashUtil;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.excalibur.source.SourceValidity;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.util.ClientUtils;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.params.FacetParams;
import org.apache.log4j.Logger;
import org.dspace.core.Context;
import org.dspace.discovery.*;
import org.dspace.services.ConfigurationService;
import org.dspace.utils.DSpace;
@@ -42,8 +37,6 @@ import java.io.Serializable;
import java.io.IOException;
import java.sql.SQLException;
import java.util.*;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.net.URLEncoder;
import java.util.List;
@@ -63,7 +56,7 @@ public class BrowseFacet extends AbstractDSpaceTransformer implements CacheableP
/**
* The cache of recently submitted items
*/
protected QueryResponse queryResults;
protected DiscoverResult queryResults;
/**
* Cached validity object
*/
@@ -72,7 +65,7 @@ public class BrowseFacet extends AbstractDSpaceTransformer implements CacheableP
/**
* Cached query arguments
*/
protected SolrQuery queryArgs;
protected DiscoverQuery queryArgs;
private int DEFAULT_PAGE_SIZE = 10;
@@ -134,23 +127,20 @@ public class BrowseFacet extends AbstractDSpaceTransformer implements CacheableP
}
// add reciently submitted items, serialize solr query contents.
QueryResponse response = getQueryResponse(dso);
DiscoverResult response = getQueryResponse(dso);
validity.add("numFound:" + response.getResults().getNumFound());
validity.add("numFound:" + response.getDspaceObjects().size());
for (SolrDocument doc : response.getResults()) {
validity.add(doc.toString());
for (DSpaceObject resultDso : response.getDspaceObjects()) {
validity.add(resultDso);
}
for (SolrDocument doc : response.getResults()) {
validity.add(doc.toString());
}
for (String facetField : response.getFacetResults().keySet()) {
validity.add(facetField);
for (FacetField field : response.getFacetFields()) {
validity.add(field.getName());
for (FacetField.Count count : field.getValues()) {
validity.add(count.getName() + count.getCount());
List<DiscoverResult.FacetResult> facetValues = response.getFacetResults().get(facetField);
for (DiscoverResult.FacetResult facetValue : facetValues) {
validity.add(facetValue.getAsFilterQuery() + facetValue.getCount());
}
}
@@ -171,7 +161,7 @@ public class BrowseFacet extends AbstractDSpaceTransformer implements CacheableP
*
* @param scope The collection.
*/
protected QueryResponse getQueryResponse(DSpaceObject scope) {
protected DiscoverResult getQueryResponse(DSpaceObject scope) {
Request request = ObjectModelHelper.getRequest(objectModel);
@@ -181,24 +171,24 @@ public class BrowseFacet extends AbstractDSpaceTransformer implements CacheableP
return queryResults;
}
queryArgs = new SolrQuery();
queryArgs = new DiscoverQuery();
//Make sure we add our default filters
queryArgs.addFilterQuery(SearchUtils.getDefaultFilters("browse"));
queryArgs.addFilterQueries(SearchUtils.getDefaultFilters("browse"));
queryArgs.setQuery("search.resourcetype: " + Constants.ITEM + ((request.getParameter("query") != null && !"".equals(request.getParameter("query"))) ? " AND (" + request.getParameter("query") + ")" : ""));
// queryArgs.setQuery("search.resourcetype:" + Constants.ITEM);
queryArgs.setRows(0);
queryArgs.setMaxResults(0);
// TODO: change this !
queryArgs.setSortField(
ConfigurationManager.getProperty("recent.submissions.sort-option"),
SolrQuery.ORDER.asc
DiscoverQuery.SORT_ORDER.asc
);
queryArgs.addFilterQuery(getParameterFacetQueries());
queryArgs.addFilterQueries(getParameterFacetQueries());
//Set the default limit to 11
@@ -207,85 +197,26 @@ public class BrowseFacet extends AbstractDSpaceTransformer implements CacheableP
//sort
//TODO: why this kind of sorting ? Should the sort not be on how many times the value appears like we do in the filter by sidebar ?
queryArgs.setFacetSort(config.getPropertyAsType("solr.browse.sort","lex"));
// queryArgs.setFacetSort(config.getPropertyAsType("solr.browse.sort","lex"));
queryArgs.setFacet(true);
// queryArgs.setFacet(true);
int offset = RequestUtils.getIntParameter(request, OFFSET);
if (offset == -1)
{
offset = 0;
}
queryArgs.setParam(FacetParams.FACET_OFFSET, String.valueOf(offset));
queryArgs.setFacetOffset(offset);
//We add +1 so we can use the extra one to make sure that we need to show the next page
queryArgs.setParam(FacetParams.FACET_LIMIT, String.valueOf(DEFAULT_PAGE_SIZE + 1));
if (scope != null) /* top level search / community */ {
if (scope instanceof Community) {
queryArgs.setFilterQueries("location:m" + scope.getID());
} else if (scope instanceof Collection) {
queryArgs.setFilterQueries("location:l" + scope.getID());
}
}
String facetField = request.getParameter(FACET_FIELD);
boolean isDate = false;
if(facetField.endsWith("_dt")){
facetField = facetField.split("_")[0];
isDate = true;
}
if (isDate) {
queryArgs.setParam(FacetParams.FACET_DATE,new String[]{facetField});
queryArgs.setParam(FacetParams.FACET_DATE_GAP,"+1YEAR");
Date lowestDate = getLowestDateValue(queryArgs.getQuery(), facetField, queryArgs.getFilterQueries());
int thisYear = Calendar.getInstance().get(Calendar.YEAR);
DateFormat formatter = new SimpleDateFormat("yyyy");
int maxEndYear = Integer.parseInt(formatter.format(lowestDate));
//Since we have a date, we need to find the last year
String startDate = "NOW/YEAR-" + SearchUtils.getConfig().getString("solr.date.gap", "10") + "YEARS";
String endDate = "NOW";
int startYear = thisYear - (offset + DEFAULT_PAGE_SIZE);
// We shouldn't go lower then our max bottom year
// Make sure to substract one so the bottom year is also counted !
if(startYear < maxEndYear)
{
startYear = maxEndYear - 1;
}
if(0 < offset){
//Say that we have an offset of 10 years
//we need to go back 10 years (2010 - (2010 - 10))
//(add one to compensate for the NOW in the start)
int endYear = thisYear - offset + 1;
endDate = "NOW/YEAR-" + (thisYear - endYear) + "YEARS";
//Add one to the startyear to get one more result
//When we select NOW, the current year is also used (so auto+1)
}
startDate = "NOW/YEAR-" + (thisYear - startYear) + "YEARS";
queryArgs.setParam(FacetParams.FACET_DATE_START, startDate);
queryArgs.setParam(FacetParams.FACET_DATE_END, endDate);
System.out.println(startDate);
System.out.println(endDate);
queryArgs.setFacetLimit(DEFAULT_PAGE_SIZE + 1);
} else {
queryArgs.addFacetField(new String[]{facetField});
}
queryArgs.addFacetField(new FacetFieldConfig(request.getParameter(FACET_FIELD), false));
try {
queryResults = searchService.search(queryArgs);
queryResults = searchService.search(context, scope, queryArgs);
} catch (SearchServiceException e) {
log.error(e.getMessage(), e);
}
@@ -300,21 +231,20 @@ public class BrowseFacet extends AbstractDSpaceTransformer implements CacheableP
* @param filterquery the filterqueries
* @return the lowest date found, in a date object
*/
private Date getLowestDateValue(String query, String dateField, String... filterquery){
private Date getLowestDateValue(Context context, String query, String dateField, String... filterquery){
try {
SolrQuery solrQuery = new SolrQuery();
solrQuery.setQuery(query);
solrQuery.setFields(dateField);
solrQuery.setRows(1);
solrQuery.setSortField(dateField, SolrQuery.ORDER.asc);
solrQuery.setFilterQueries(filterquery);
DiscoverQuery discoverQuery = new DiscoverQuery();
discoverQuery.setQuery(query);
discoverQuery.setMaxResults(1);
discoverQuery.setSortField(dateField, DiscoverQuery.SORT_ORDER.asc);
discoverQuery.addFilterQueries(filterquery);
QueryResponse rsp = searchService.search(solrQuery);
if(0 < rsp.getResults().getNumFound()){
return (Date) rsp.getResults().get(0).getFieldValue(dateField);
}
DiscoverResult rsp = searchService.search(context, discoverQuery);
// if(0 < rsp.getResults().getNumFound()){
// return (Date) rsp.getResults().get(0).getFieldValue(dateField);
// }
}catch (Exception e){
log.error("Unable to get lowest date", e);
}
@@ -358,37 +288,30 @@ public class BrowseFacet extends AbstractDSpaceTransformer implements CacheableP
queryResults = getQueryResponse(dso);
if (this.queryResults != null) {
java.util.List<FacetField> facetFields = this.queryResults.getFacetFields();
Map<String, List<DiscoverResult.FacetResult>> facetFields = this.queryResults.getFacetResults();
if (facetFields == null)
{
facetFields = new ArrayList<FacetField>();
facetFields = new LinkedHashMap<String, List<DiscoverResult.FacetResult>>();
}
facetFields.addAll(this.queryResults.getFacetDates());
// facetFields.addAll(this.queryResults.getFacetDates());
if (facetFields.size() > 0) {
FacetField field = facetFields.get(0);
java.util.List<FacetField.Count> values = field.getValues();
if(field.getGap() != null){
//We are dealing with dates so flip em, top date comes first
Collections.reverse(values);
}
String facetField = String.valueOf(facetFields.keySet().toArray(new String[facetFields.size()])[0]);
java.util.List<DiscoverResult.FacetResult> values = facetFields.get(facetField);
if (values != null && 0 < values.size()) {
Division results = body.addDivision("browse-by-" + field + "-results", "primary");
Division results = body.addDivision("browse-by-" + facetField + "-results", "primary");
results.setHead(message("xmlui.ArtifactBrowser.AbstractSearch.type_" + request.getParameter(FACET_FIELD) + "_browse"));
// Find our faceting offset
int offSet = 0;
try {
offSet = Integer.parseInt(queryArgs.get(FacetParams.FACET_OFFSET));
} catch (NumberFormatException e) {
//Ignore
int offSet = queryArgs.getFacetOffset();
if(offSet == -1){
offSet = 0;
}
//Only show the nextpageurl if we have at least one result following our current results
@@ -398,11 +321,11 @@ public class BrowseFacet extends AbstractDSpaceTransformer implements CacheableP
nextPageUrl = getNextPageURL(request);
}
results.setSimplePagination((int) queryResults.getResults().getNumFound(), offSet + 1,
results.setSimplePagination((int) queryResults.getDspaceObjects().size(), offSet + 1,
(offSet + (values.size() - 1)), getPreviousPageURL(request), nextPageUrl);
Table singleTable = results.addTable("browse-by-" + field + "-results", (int) (queryResults.getResults().getNumFound() + 1), 1);
Table singleTable = results.addTable("browse-by-" + facetField + "-results", (int) (queryResults.getDspaceObjects().size() + 1), 1);
List<String> filterQueries = new ArrayList<String>();
if(request.getParameterValues("fq") != null)
@@ -410,20 +333,17 @@ public class BrowseFacet extends AbstractDSpaceTransformer implements CacheableP
filterQueries = Arrays.asList(request.getParameterValues("fq"));
}
for (int i = 0; i < values.size(); i++) {
FacetField.Count value = values.get(i);
DiscoverResult.FacetResult value = values.get(i);
String displayedValue = value.getName();
String displayedValue = value.getDisplayedValue();
String filterQuery = value.getAsFilterQuery();
if (field.getName().equals("location.comm") || field.getName().equals("location.coll")) {
//We have a community/collection, resolve it to a dspaceObject
displayedValue = SolrServiceImpl.locationToName(context, field.getName(), displayedValue);
}
if(field.getGap() != null){
//We have a date get the year so we can display it
DateFormat simpleDateformat = new SimpleDateFormat("yyyy");
displayedValue = simpleDateformat.format(SolrServiceImpl.toDate(displayedValue));
filterQuery = ClientUtils.escapeQueryChars(value.getFacetField().getName()) + ":" + displayedValue + "*";
}
// if(field.getGap() != null){
// //We have a date get the year so we can display it
// DateFormat simpleDateformat = new SimpleDateFormat("yyyy");
// displayedValue = simpleDateformat.format(SolrServiceImpl.toDate(displayedValue));
// filterQuery = ClientUtils.escapeQueryChars(value.getFacetField().getName()) + ":" + displayedValue + "*";
// }
Cell cell = singleTable.addRow().addCell();
@@ -468,9 +388,9 @@ public class BrowseFacet extends AbstractDSpaceTransformer implements CacheableP
private String getNextPageURL(Request request) {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put(FACET_FIELD, request.getParameter(FACET_FIELD));
if (queryArgs.get(FacetParams.FACET_OFFSET) != null)
if (queryArgs.getFacetOffset() != -1)
{
parameters.put(OFFSET, String.valueOf(Integer.parseInt(queryArgs.get(FacetParams.FACET_OFFSET)) + DEFAULT_PAGE_SIZE));
parameters.put(OFFSET, String.valueOf(queryArgs.getFacetOffset() + DEFAULT_PAGE_SIZE));
}
// Add the filter queries
@@ -490,16 +410,16 @@ public class BrowseFacet extends AbstractDSpaceTransformer implements CacheableP
private String getPreviousPageURL(Request request) {
//If our offset should be 0 then we shouldn't be able to view a previous page url
if ("0".equals(queryArgs.get(FacetParams.FACET_OFFSET)))
if (0 == queryArgs.getFacetOffset())
{
return null;
}
Map<String, String> parameters = new HashMap<String, String>();
parameters.put(FACET_FIELD, request.getParameter(FACET_FIELD));
if (queryArgs.get(FacetParams.FACET_OFFSET) != null)
if (queryArgs.getFacetOffset() != -1)
{
parameters.put(OFFSET, String.valueOf(Integer.parseInt(queryArgs.get(FacetParams.FACET_OFFSET)) - DEFAULT_PAGE_SIZE));
parameters.put(OFFSET, String.valueOf(queryArgs.getFacetOffset() - DEFAULT_PAGE_SIZE));
}
// Add the filter queries

View File

@@ -1,17 +1,12 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
* tree and avaiNlable online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.xmlui.aspect.discovery;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.dspace.core.Constants;
import org.dspace.discovery.SearchUtils;
import org.apache.solr.common.SolrDocument;
import org.dspace.app.xmlui.utils.HandleUtil;
import org.dspace.app.xmlui.wing.Message;
import org.dspace.app.xmlui.wing.WingException;
@@ -33,31 +28,34 @@ import java.sql.SQLException;
* @author Mark Diggory (markd at atmire dot com)
* @author Ben Bosman (ben at atmire dot com)
*/
public class CollectionRecentSubmissions extends AbstractFiltersTransformer {
public class CollectionRecentSubmissions extends AbstractRecentSubmissionTransformer {
private static final Logger log = Logger.getLogger(CollectionRecentSubmissions.class);
private static final Message T_head_recent_submissions =
message("xmlui.ArtifactBrowser.CollectionViewer.head_recent_submissions");
/**
* Display a single collection
* Displays the recent submissions for this collection
*/
public void addBody(Body body) throws SAXException, WingException,
SQLException, IOException, AuthorizeException {
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
// Set up the major variables
Collection collection = (Collection) dso;
if(!(dso instanceof Collection))
{
return;
}
performSearch(collection);
getRecentlySubmittedItems(collection);
//Only attempt to render our result if we have one.
if(queryResults == null)
{
return;
}// queryResults;
}
// Build the collection viewer division.
Division home = body.addDivision("collection-home", "primary repository collection");
@@ -71,48 +69,8 @@ public class CollectionRecentSubmissions extends AbstractFiltersTransformer {
"collection-last-submitted", ReferenceSet.TYPE_SUMMARY_LIST,
null, "recent-submissions");
for (SolrDocument doc : queryResults.getResults()) {
lastSubmitted.addReference(
SearchUtils.findDSpaceObject(context, doc));
}
}
/**
* Get the recently submitted items for the given community or collection.
*
* @param scope The comm/collection.
* @return the response of the query
*/
public void performSearch(DSpaceObject scope) {
if(queryResults != null)
{
return;
}// queryResults;
queryArgs = prepareDefaultFilters(getView());
queryArgs.setQuery("search.resourcetype:" + Constants.ITEM);
queryArgs.setRows(SearchUtils.getConfig().getInt("solr.recent-submissions.size", 5));
String sortField = SearchUtils.getConfig().getString("recent.submissions.sort-option");
if(sortField != null){
queryArgs.setSortField(
sortField,
SolrQuery.ORDER.desc
);
}
queryArgs.setFilterQueries("location:l" + scope.getID());
try {
queryResults = getSearchService().search(queryArgs);
} catch (RuntimeException e) {
log.error(e.getMessage(),e);
} catch (Exception e) {
log.error(e.getMessage(),e);
for (DSpaceObject resultObj : queryResults.getDspaceObjects()) {
lastSubmitted.addReference(resultObj);
}
}

View File

@@ -10,9 +10,6 @@ package org.dspace.app.xmlui.aspect.discovery;
import java.io.IOException;
import java.sql.SQLException;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.common.SolrDocument;
import org.dspace.app.xmlui.utils.HandleUtil;
import org.dspace.app.xmlui.utils.UIException;
import org.dspace.app.xmlui.wing.Message;
@@ -23,8 +20,6 @@ import org.dspace.app.xmlui.wing.element.ReferenceSet;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Community;
import org.dspace.content.DSpaceObject;
import org.dspace.core.Constants;
import org.dspace.discovery.SearchUtils;
import org.xml.sax.SAXException;
/**
@@ -34,19 +29,13 @@ import org.xml.sax.SAXException;
* @author Mark Diggory (markd at atmire dot com)
* @author Ben Bosman (ben at atmire dot com)
*/
public class CommunityRecentSubmissions extends AbstractFiltersTransformer
{
private static final Logger log = Logger.getLogger(CommunityRecentSubmissions.class);
public class CommunityRecentSubmissions extends AbstractRecentSubmissionTransformer {
private static final Message T_head_recent_submissions =
message("xmlui.ArtifactBrowser.CollectionViewer.head_recent_submissions");
message("xmlui.ArtifactBrowser.CommunityViewer.head_recent_submissions");
/**
* Display a single community (and refrence any sub communites or
* collections)
* Displays the recent submissions for this community
*/
public void addBody(Body body) throws SAXException, WingException,
UIException, SQLException, IOException, AuthorizeException
@@ -61,7 +50,13 @@ public class CommunityRecentSubmissions extends AbstractFiltersTransformer
// Build the community viewer division.
Division home = body.addDivision("community-home", "primary repository community");
performSearch(dso);
getRecentlySubmittedItems(dso);
//Only attempt to render our result if we have one.
if(queryResults == null)
{
return;
}
Division lastSubmittedDiv = home
.addDivision("community-recent-submission", "secondary recent-submission");
@@ -72,56 +67,13 @@ public class CommunityRecentSubmissions extends AbstractFiltersTransformer
"community-last-submitted", ReferenceSet.TYPE_SUMMARY_LIST,
null, "recent-submissions");
for (SolrDocument doc : queryResults.getResults()) {
lastSubmitted.addReference(SearchUtils.findDSpaceObject(context, doc));
for (DSpaceObject resultObject : queryResults.getDspaceObjects()) {
lastSubmitted.addReference(resultObject);
}
}
/**
* Get the recently submitted items for the given community or collection.
*
* @param scope The comm/collection.
* @return the response of the query
*/
public void performSearch(DSpaceObject scope) {
if(queryResults != null)
{
return;
}// queryResults;
queryArgs = prepareDefaultFilters(getView());
queryArgs.setQuery("search.resourcetype:" + Constants.ITEM);
queryArgs.setRows(SearchUtils.getConfig().getInt("solr.recent-submissions.size", 5));
String sortField = SearchUtils.getConfig().getString("recent.submissions.sort-option");
if(sortField != null){
queryArgs.setSortField(
sortField,
SolrQuery.ORDER.desc
);
}
/* Set the communities facet filters */
queryArgs.setFilterQueries("location:m" + scope.getID());
try {
queryResults = getSearchService().search(queryArgs);
} catch (RuntimeException e) {
log.error(e.getMessage(),e);
} catch (Exception e) {
log.error(e.getMessage(),e);
}
}
public String getView()
{
return "community";
}
}

View File

@@ -1,75 +0,0 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.xmlui.aspect.discovery;
/**
* Class used to display facets for an item
*
* @author Kevin Van de Velde (kevin at atmire dot com)
* @author Mark Diggory (markd at atmire dot com)
* @author Ben Bosman (ben at atmire dot com)
*/
public class ItemFacets extends org.dspace.app.xmlui.aspect.discovery.AbstractFiltersTransformer
{
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(org.dspace.app.xmlui.aspect.discovery.ItemFacets.class);
/**
* Display a single item
*/
public void addBody(org.dspace.app.xmlui.wing.element.Body body) throws org.xml.sax.SAXException, org.dspace.app.xmlui.wing.WingException,
org.dspace.app.xmlui.utils.UIException, java.sql.SQLException, java.io.IOException, org.dspace.authorize.AuthorizeException
{
org.dspace.content.DSpaceObject dso = org.dspace.app.xmlui.utils.HandleUtil.obtainHandle(objectModel);
if (!(dso instanceof org.dspace.content.Item))
{
return;
}
org.dspace.content.Item item = (org.dspace.content.Item) dso;
try {
performSearch(item);
} catch (org.dspace.discovery.SearchServiceException e) {
log.error(e.getMessage(),e);
}
}
@Override
public void performSearch(org.dspace.content.DSpaceObject dso) throws org.dspace.discovery.SearchServiceException {
if(queryResults != null)
{
return;
}
this.queryArgs = prepareDefaultFilters(getView());
this.queryArgs.setRows(1);
this.queryArgs.setQuery("handle:" + dso.getHandle());
queryResults = getSearchService().search(queryArgs);
}
public String getView()
{
return "item";
}
/**
* Recycle
*/
public void recycle() {
this.queryArgs = null;
this.queryResults = null;
super.recycle();
}
}

View File

@@ -9,14 +9,9 @@ package org.dspace.app.xmlui.aspect.discovery;
import java.io.IOException;
import java.sql.SQLException;
import java.util.*;
import java.util.List;
import org.apache.log4j.Logger;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrDocument;
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
import org.dspace.app.xmlui.utils.HandleUtil;
import org.dspace.app.xmlui.utils.UIException;
import org.dspace.app.xmlui.wing.WingException;
@@ -24,7 +19,8 @@ import org.dspace.app.xmlui.wing.element.*;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.core.LogManager;
import org.dspace.discovery.DiscoverQuery;
import org.dspace.discovery.DiscoverResult;
import org.dspace.discovery.SearchUtils;
import org.xml.sax.SAXException;
import org.dspace.discovery.SearchServiceException;
@@ -36,8 +32,17 @@ import org.dspace.discovery.SearchServiceException;
* @author Mark Diggory (markd at atmire dot com)
* @author Ben Bosman (ben at atmire dot com)
*/
public class RelatedItems extends AbstractFiltersTransformer
public class RelatedItems extends AbstractDSpaceTransformer
{
/**
* Cached query results
*/
protected DiscoverResult queryResults;
/**
* Cached query arguments
*/
protected DiscoverQuery queryArgs;
private static final Logger log = Logger.getLogger(RelatedItems.class);
@@ -65,7 +70,8 @@ public class RelatedItems extends AbstractFiltersTransformer
if (this.queryResults != null) {
// TODO: develop this !
/*
NamedList nList = this.queryResults.getResponse();
SimpleOrderedMap<SolrDocumentList> mlt = (SimpleOrderedMap<SolrDocumentList>)nList.get("moreLikeThis");
@@ -118,20 +124,20 @@ public class RelatedItems extends AbstractFiltersTransformer
}
}
}
*/
}
}
@Override
public void performSearch(DSpaceObject dso) throws SearchServiceException {
if(queryResults != null)
{
return;
}
/*
this.queryArgs = prepareDefaultFilters(getView());
this.queryArgs.setRows(1);
this.queryArgs.setMaxResults(1);
this.queryArgs.add("fl","author,handle");
this.queryArgs.add("mlt","true");
this.queryArgs.add("mlt.fl","author,handle");
@@ -139,8 +145,8 @@ public class RelatedItems extends AbstractFiltersTransformer
this.queryArgs.add("mlt.mintf","1");
this.queryArgs.setQuery("handle:" + dso.getHandle());
this.queryArgs.setRows(1);
queryResults = getSearchService().search(queryArgs);
*/
queryResults = SearchUtils.getSearchService().search(context, queryArgs);
}

View File

@@ -13,12 +13,6 @@ import org.apache.cocoon.environment.Request;
import org.apache.cocoon.util.HashUtil;
import org.apache.excalibur.source.SourceValidity;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.util.ClientUtils;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.params.FacetParams;
import org.dspace.app.util.Util;
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
import org.dspace.app.xmlui.utils.DSpaceValidity;
@@ -33,10 +27,7 @@ import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.DSpaceObject;
import org.dspace.core.Constants;
import org.dspace.discovery.SearchService;
import org.dspace.discovery.SearchServiceException;
import org.dspace.discovery.SearchUtils;
import org.dspace.discovery.SolrServiceImpl;
import org.dspace.discovery.*;
import org.dspace.services.ConfigurationService;
import org.dspace.utils.DSpace;
import org.xml.sax.SAXException;
@@ -44,10 +35,7 @@ import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
@@ -69,7 +57,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
/**
* The cache of recently submitted items
*/
protected QueryResponse queryResults;
protected DiscoverResult queryResults;
/**
* Cached validity object
*/
@@ -78,7 +66,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
/**
* Cached query arguments
*/
protected SolrQuery queryArgs;
protected DiscoverQuery queryArgs;
private int DEFAULT_PAGE_SIZE = 10;
@@ -139,23 +127,20 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
}
// add reciently submitted items, serialize solr query contents.
QueryResponse response = getQueryResponse(dso);
DiscoverResult response = getQueryResponse(dso);
validity.add("numFound:" + response.getResults().getNumFound());
validity.add("numFound:" + response.getDspaceObjects().size());
for (SolrDocument doc : response.getResults()) {
validity.add(doc.toString());
for (DSpaceObject resultDso : queryResults.getDspaceObjects()) {
validity.add(resultDso);
}
for (SolrDocument doc : response.getResults()) {
validity.add(doc.toString());
}
for (String facetField : queryResults.getFacetResults().keySet()) {
validity.add(facetField);
for (FacetField field : response.getFacetFields()) {
validity.add(field.getName());
for (FacetField.Count count : field.getValues()) {
validity.add(count.getName() + count.getCount());
java.util.List<DiscoverResult.FacetResult> facetValues = queryResults.getFacetResults().get(facetField);
for (DiscoverResult.FacetResult facetValue : facetValues) {
validity.add(facetValue.getAsFilterQuery() + facetValue.getCount());
}
}
@@ -176,7 +161,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
*
* @param scope The collection.
*/
protected QueryResponse getQueryResponse(DSpaceObject scope) {
protected DiscoverResult getQueryResponse(DSpaceObject scope) {
Request request = ObjectModelHelper.getRequest(objectModel);
@@ -186,18 +171,19 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
return queryResults;
}
queryArgs = new SolrQuery();
queryArgs = new DiscoverQuery();
//Make sure we add our default filters
queryArgs.addFilterQuery(SearchUtils.getDefaultFilters("search"));
queryArgs.addFilterQueries(SearchUtils.getDefaultFilters("search"));
queryArgs.setQuery("search.resourcetype: " + Constants.ITEM + ((request.getParameter("query") != null && !"".equals(request.getParameter("query"))) ? " AND (" + request.getParameter("query") + ")" : ""));
queryArgs.setQuery(((request.getParameter("query") != null && !"".equals(request.getParameter("query").trim())) ? request.getParameter("query") : null));
// queryArgs.setQuery("search.resourcetype:" + Constants.ITEM);
queryArgs.setDSpaceObjectFilter(Constants.ITEM);
queryArgs.setRows(0);
queryArgs.setMaxResults(0);
queryArgs.addFilterQuery(getParameterFilterQueries());
queryArgs.addFilterQueries(getDiscoveryFilterQueries());
//Set the default limit to 11
@@ -206,9 +192,8 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
//sort
//TODO: why this kind of sorting ? Should the sort not be on how many times the value appears like we do in the filter by sidebar ?
queryArgs.setFacetSort(config.getPropertyAsType("solr.browse.sort","lex"));
queryArgs.setFacetSort(DiscoverQuery.FACET_SORT.INDEX);
queryArgs.setFacet(true);
String facetField = request.getParameter(SearchFilterParam.FACET_FIELD);
@@ -217,87 +202,25 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
{
offset = 0;
}
if(facetField.endsWith(".year")){
// TODO: dates are now handled in another way, throw this away?
queryArgs.setParam(FacetParams.FACET_OFFSET, "0");
queryArgs.setParam(FacetParams.FACET_LIMIT, "1000000");
} else {
queryArgs.setParam(FacetParams.FACET_OFFSET, String.valueOf(offset));
queryArgs.setFacetOffset(offset);
//We add +1 so we can use the extra one to make sure that we need to show the next page
queryArgs.setParam(FacetParams.FACET_LIMIT, String.valueOf(DEFAULT_PAGE_SIZE + 1));
}
queryArgs.setFacetLimit(DEFAULT_PAGE_SIZE + 1);
if (scope != null) /* top level search / community */ {
if (scope instanceof Community) {
queryArgs.setFilterQueries("location:m" + scope.getID());
} else if (scope instanceof Collection) {
queryArgs.setFilterQueries("location:l" + scope.getID());
}
}
boolean isDate = false;
if(facetField.endsWith("_dt")){
facetField = facetField.split("_")[0];
isDate = true;
}
if (isDate) {
queryArgs.setParam(FacetParams.FACET_DATE, facetField);
queryArgs.setParam(FacetParams.FACET_DATE_GAP,"+1YEAR");
Date lowestDate = getLowestDateValue(queryArgs.getQuery(), facetField, queryArgs.getFilterQueries());
int thisYear = Calendar.getInstance().get(Calendar.YEAR);
DateFormat formatter = new SimpleDateFormat("yyyy");
int maxEndYear = Integer.parseInt(formatter.format(lowestDate));
//Since we have a date, we need to find the last year
String startDate = "NOW/YEAR-" + SearchUtils.getConfig().getString("solr.date.gap", "10") + "YEARS";
String endDate = "NOW";
int startYear = thisYear - (offset + DEFAULT_PAGE_SIZE);
// We shouldn't go lower then our max bottom year
// Make sure to substract one so the bottom year is also counted !
if(startYear < maxEndYear)
FacetFieldConfig facetFieldConfig;
if(request.getParameter(SearchFilterParam.STARTS_WITH) != null)
{
startYear = maxEndYear - 1;
facetFieldConfig = new FacetFieldConfig(facetField, false, request.getParameter(SearchFilterParam.STARTS_WITH).toLowerCase());
}else{
facetFieldConfig = new FacetFieldConfig(facetField, false);
}
if(0 < offset){
//Say that we have an offset of 10 years
//we need to go back 10 years (2010 - (2010 - 10))
//(add one to compensate for the NOW in the start)
int endYear = thisYear - offset + 1;
endDate = "NOW/YEAR-" + (thisYear - endYear) + "YEARS";
//Add one to the startyear to get one more result
//When we select NOW, the current year is also used (so auto+1)
}
startDate = "NOW/YEAR-" + (thisYear - startYear) + "YEARS";
queryArgs.addFacetField(facetFieldConfig);
queryArgs.setParam(FacetParams.FACET_DATE_START, startDate);
queryArgs.setParam(FacetParams.FACET_DATE_END, endDate);
System.out.println(startDate);
System.out.println(endDate);
} else {
if(request.getParameter(SearchFilterParam.STARTS_WITH) != null)
{
queryArgs.setFacetPrefix(facetField, request.getParameter(SearchFilterParam.STARTS_WITH).toLowerCase());
}
queryArgs.addFacetField(facetField);
}
try {
queryResults = searchService.search(queryArgs);
queryResults = searchService.search(context, scope, queryArgs);
} catch (SearchServiceException e) {
log.error(e.getMessage(), e);
}
@@ -306,34 +229,6 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
}
/**
* Retrieves the lowest date value in the given field
* @param query a solr query
* @param dateField the field for which we want to retrieve our date
* @param filterquery the filterqueries
* @return the lowest date found, in a date object
*/
private Date getLowestDateValue(String query, String dateField, String... filterquery){
try {
SolrQuery solrQuery = new SolrQuery();
solrQuery.setQuery(query);
solrQuery.setFields(dateField);
solrQuery.setRows(1);
solrQuery.setSortField(dateField, SolrQuery.ORDER.asc);
solrQuery.setFilterQueries(filterquery);
QueryResponse rsp = searchService.search(solrQuery);
if(0 < rsp.getResults().getNumFound()){
return (Date) rsp.getResults().get(0).getFieldValue(dateField);
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
/**
* Add a page title and trail links.
*/
public void addPageMeta(PageMeta pageMeta) throws SAXException, WingException, SQLException, IOException, AuthorizeException {
@@ -374,25 +269,20 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
queryResults = getQueryResponse(dso);
if (this.queryResults != null) {
java.util.List<FacetField> facetFields = this.queryResults.getFacetFields();
Map<String, List<DiscoverResult.FacetResult>> facetFields = this.queryResults.getFacetResults();
if (facetFields == null)
{
facetFields = new ArrayList<FacetField>();
facetFields = new LinkedHashMap<String, List<DiscoverResult.FacetResult>>();
}
facetFields.addAll(this.queryResults.getFacetDates());
// facetFields.addAll(this.queryResults.getFacetDates());
if (facetFields.size() > 0) {
FacetField field = facetFields.get(0);
java.util.List<FacetField.Count> values = field.getValues();
if(field.getGap() != null){
//We are dealing with dates so flip em, top date comes first
Collections.reverse(values);
String facetField = facetFields.keySet().toArray(new String[facetFields.size()])[0];
java.util.List<DiscoverResult.FacetResult> values = facetFields.get(facetField);
}
Division results = body.addDivision("browse-by-" + field + "-results", "primary");
Division results = body.addDivision("browse-by-" + facetField + "-results", "primary");
results.setHead(message("xmlui.Discovery.AbstractSearch.type_" + browseParams.getFacetField()));
if (values != null && 0 < values.size()) {
@@ -400,16 +290,14 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
// Find our faceting offset
int offSet = 0;
try {
offSet = Integer.parseInt(queryArgs.get(FacetParams.FACET_OFFSET));
} catch (NumberFormatException e) {
//Ignore
int offSet = queryArgs.getFacetOffset();
if(offSet == -1){
offSet = 0;
}
//Only show the nextpageurl if we have at least one result following our current results
String nextPageUrl = null;
if(field.getName().endsWith(".year")){
if(facetField.endsWith(".year")){
offSet = Util.getIntParameter(request, SearchFilterParam.OFFSET);
offSet = offSet == -1 ? 0 : offSet;
@@ -428,7 +316,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
int shownItemsMax;
if(field.getName().endsWith(".year")){
if(facetField.endsWith(".year")){
if((values.size() - offSet) < DEFAULT_PAGE_SIZE)
{
shownItemsMax = values.size();
@@ -447,7 +335,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
results.setSimplePagination(-1, offSet + 1,
shownItemsMax, getPreviousPageURL(browseParams, request), nextPageUrl);
Table singleTable = results.addTable("browse-by-" + field + "-results", (int) (queryResults.getResults().getNumFound() + 1), 1);
Table singleTable = results.addTable("browse-by-" + facetField + "-results", (int) (queryResults.getDspaceObjects().size() + 1), 1);
List<String> filterQueries = new ArrayList<String>();
if(request.getParameterValues("fq") != null)
@@ -455,7 +343,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
filterQueries = Arrays.asList(request.getParameterValues("fq"));
}
if(field.getName().endsWith(".year")){
if(facetField.endsWith(".year")){
int start = (values.size() - 1) - offSet;
int end = start - DEFAULT_PAGE_SIZE;
if(end < 0)
@@ -468,9 +356,9 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
}
for(int i = start; end <= i; i--)
{
FacetField.Count value = values.get(i);
DiscoverResult.FacetResult value = values.get(i);
renderFacetField(browseParams, dso, field, singleTable, filterQueries, value);
renderFacetField(browseParams, dso, facetField, singleTable, filterQueries, value);
}
}else{
int end = values.size();
@@ -481,9 +369,9 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
for (int i = 0; i < end; i++) {
FacetField.Count value = values.get(i);
DiscoverResult.FacetResult value = values.get(i);
renderFacetField(browseParams, dso, field, singleTable, filterQueries, value);
renderFacetField(browseParams, dso, facetField, singleTable, filterQueries, value);
}
}
@@ -496,9 +384,16 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
}
private void addBrowseJumpNavigation(Division div, SearchFilterParam browseParams, Request request)
throws WingException
{
Division jump = div.addInteractiveDivision("filter-navigation", contextPath + "/search-filter",
throws WingException, SQLException {
String action;
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
if(dso != null){
action = contextPath + "/handle/" + dso.getHandle() + "/search-filter";
}else{
action = contextPath + "/search-filter";
}
Division jump = div.addInteractiveDivision("filter-navigation", action,
Division.METHOD_POST, "secondary navigation");
Map<String, String> params = new HashMap<String, String>();
@@ -540,25 +435,21 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
}
}
private void renderFacetField(SearchFilterParam browseParams, DSpaceObject dso, FacetField field, Table singleTable, List<String> filterQueries, FacetField.Count value) throws SQLException, WingException, UnsupportedEncodingException {
String displayedValue = value.getName();
private void renderFacetField(SearchFilterParam browseParams, DSpaceObject dso, String facetField, Table singleTable, List<String> filterQueries, DiscoverResult.FacetResult value) throws SQLException, WingException, UnsupportedEncodingException {
String displayedValue = value.getDisplayedValue();
String filterQuery = value.getAsFilterQuery();
if (field.getName().equals("location.comm") || field.getName().equals("location.coll")) {
//We have a community/collection, resolve it to a dspaceObject
displayedValue = SolrServiceImpl.locationToName(context, field.getName(), displayedValue);
}
if(field.getGap() != null){
//We have a date get the year so we can display it
DateFormat simpleDateformat = new SimpleDateFormat("yyyy");
displayedValue = simpleDateformat.format(SolrServiceImpl.toDate(displayedValue));
filterQuery = ClientUtils.escapeQueryChars(value.getFacetField().getName()) + ":" + displayedValue + "*";
}
// if(field.getGap() != null){
// //We have a date get the year so we can display it
// DateFormat simpleDateformat = new SimpleDateFormat("yyyy");
// displayedValue = simpleDateformat.format(SolrServiceImpl.toDate(displayedValue));
// filterQuery = ClientUtils.escapeQueryChars(value.getFacetField().getName()) + ":" + displayedValue + "*";
// }
Cell cell = singleTable.addRow().addCell();
//No use in selecting the same filter twice
if(filterQueries.contains(filterQuery)){
cell.addContent(SearchUtils.getFilterQueryDisplay(displayedValue) + " (" + value.getCount() + ")");
cell.addContent(displayedValue + " (" + value.getCount() + ")");
} else {
//Add the basics
Map<String, String> urlParams = new HashMap<String, String>();
@@ -568,7 +459,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
url = addFilterQueriesToUrl(url);
//Last add the current filter query
url += "&fq=" + filterQuery;
cell.addXref(url, SearchUtils.getFilterQueryDisplay(displayedValue) + " (" + value.getCount() + ")"
cell.addXref(url, displayedValue + " (" + value.getCount() + ")"
);
}
}
@@ -595,7 +486,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
private String getPreviousPageURL(SearchFilterParam browseParams, Request request) {
//If our offset should be 0 then we shouldn't be able to view a previous page url
if ("0".equals(queryArgs.get(FacetParams.FACET_OFFSET)) && Util.getIntParameter(request, "offset") == -1)
if (0 == queryArgs.getFacetOffset() && Util.getIntParameter(request, "offset") == -1)
{
return null;
}
@@ -644,15 +535,65 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
}
private String[] getParameterFilterQueries() {
protected String[] getParameterFilterQueries() {
Request request = ObjectModelHelper.getRequest(objectModel);
return request.getParameterValues("fq") != null ? request.getParameterValues("fq") : new String[0];
java.util.List<String> fqs = new ArrayList<String>();
if(request.getParameterValues("fq") != null)
{
fqs.addAll(Arrays.asList(request.getParameterValues("fq")));
}
//Have we added a filter using the UI
if(request.getParameter("filter") != null && !"".equals(request.getParameter("filter")))
{
fqs.add((request.getParameter("filtertype").equals("*") ? "" : request.getParameter("filtertype") + ":") + request.getParameter("filter"));
}
return fqs.toArray(new String[fqs.size()]);
}
/**
* Returns all the filter queries for use by discovery
* This method returns more expanded filter queries then the getParameterFilterQueries
* @return an array containing the filter queries
* TODO: almost identical to: SimpleSearch.getFilterQueries
*/
protected String[] getDiscoveryFilterQueries() {
try {
java.util.List<String> allFilterQueries = new ArrayList<String>();
Request request = ObjectModelHelper.getRequest(objectModel);
java.util.List<String> fqs = new ArrayList<String>();
if(request.getParameterValues("fq") != null)
{
fqs.addAll(Arrays.asList(request.getParameterValues("fq")));
}
String type = request.getParameter("filtertype");
String value = request.getParameter("filter");
if(value != null && !value.equals("")){
allFilterQueries.add(searchService.toFilterQuery(context, (type.equals("*") ? "" : type), value).getFilterQuery());
}
//Add all the previous filters also
for (String fq : fqs) {
allFilterQueries.add(searchService.toFilterQuery(context, fq).getFilterQuery());
}
return allFilterQueries.toArray(new String[allFilterQueries.size()]);
}
catch (RuntimeException re) {
throw re;
} catch (Exception e) {
return null;
}
}
private static class SearchFilterParam {
private Request request;
/** The always present commond params **/
public static final String QUERY = "query";
public static final String FACET_FIELD = "field";
/** The browse control params **/
@@ -671,6 +612,8 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
public Map<String, String> getCommonBrowseParams(){
Map<String, String> result = new HashMap<String, String>();
result.put(FACET_FIELD, request.getParameter(FACET_FIELD));
if(request.getParameter(QUERY) != null)
result.put(QUERY, request.getParameter(QUERY));
return result;
}

View File

@@ -7,15 +7,12 @@
*/
package org.dspace.app.xmlui.aspect.discovery;
import org.apache.cocoon.caching.CacheableProcessingComponent;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.util.HashUtil;
import org.apache.excalibur.source.SourceValidity;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
import org.dspace.app.xmlui.utils.DSpaceValidity;
import org.dspace.app.xmlui.utils.HandleUtil;
@@ -25,13 +22,12 @@ import org.dspace.app.xmlui.wing.WingException;
import org.dspace.app.xmlui.wing.element.List;
import org.dspace.app.xmlui.wing.element.Options;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Community;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.dspace.discovery.SearchService;
import org.dspace.discovery.SearchServiceException;
import org.dspace.discovery.SearchUtils;
import org.dspace.discovery.SolrServiceImpl;
import org.dspace.handle.HandleManager;
import org.dspace.discovery.*;
import org.dspace.utils.DSpace;
import org.xml.sax.SAXException;
@@ -49,23 +45,20 @@ import java.util.regex.Pattern;
* @author Mark Diggory (markd at atmire dot com)
* @author Ben Bosman (ben at atmire dot com)
*/
public abstract class AbstractFiltersTransformer extends AbstractDSpaceTransformer {
public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implements CacheableProcessingComponent {
private static final Logger log = Logger.getLogger(AbstractFiltersTransformer.class);
private static final Logger log = Logger.getLogger(SidebarFacetsTransformer.class);
public abstract String getView();
/**
* Cached query results
*/
protected QueryResponse queryResults;
protected DiscoverResult queryResults;
/**
* Cached query arguments
*/
protected SolrQuery queryArgs;
protected DiscoverQuery queryArgs;
/**
* Cached validity object
@@ -90,13 +83,12 @@ public abstract class AbstractFiltersTransformer extends AbstractDSpaceTransform
public Serializable getKey() {
try {
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
if (dso == null)
if (dso != null)
{
return HashUtil.hash(dso.getHandle());
}else{
return "0";
}
return HashUtil.hash(dso.getHandle());
}
catch (SQLException sqle) {
// Ignore all errors and just return that the component is not
@@ -117,12 +109,10 @@ public abstract class AbstractFiltersTransformer extends AbstractDSpaceTransform
try {
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
DSpaceValidity val = new DSpaceValidity();
// add reciently submitted items, serialize solr query contents.
performSearch(dso);
// Retrieve any facet results to add to the validity key
performSearch();
// Add the actual collection;
if (dso != null)
@@ -130,71 +120,173 @@ public abstract class AbstractFiltersTransformer extends AbstractDSpaceTransform
val.add(dso);
}
val.add("numFound:" + queryResults.getResults().getNumFound());
val.add("numFound:" + queryResults.getDspaceObjects().size());
for (SolrDocument doc : queryResults.getResults()) {
val.add(doc.toString());
for (DSpaceObject resultDso : queryResults.getDspaceObjects()) {
val.add(resultDso);
}
for (SolrDocument doc : queryResults.getResults()) {
val.add(doc.toString());
}
for (String facetField : queryResults.getFacetResults().keySet()) {
val.add(facetField);
for (FacetField field : queryResults.getFacetFields()) {
val.add(field.getName());
for (FacetField.Count count : field.getValues()) {
val.add(count.getName() + count.getCount());
java.util.List<DiscoverResult.FacetResult> facetValues = queryResults.getFacetResults().get(facetField);
for (DiscoverResult.FacetResult facetValue : facetValues) {
val.add(facetValue.getAsFilterQuery() + facetValue.getCount());
}
}
this.validity = val.complete();
}
catch (Exception e) {
log.error(e.getMessage(),e);
}
//TODO: dependent on tags as well :)
}
return this.validity;
}
public abstract void performSearch(DSpaceObject object) throws SearchServiceException, UIException;
/**
* Determine the current scope. This may be derived from the current url
* handle if present or the scope parameter is given. If no scope is
* specified then null is returned.
*
* @return The current scope.
*/
protected DSpaceObject getScope() throws SQLException {
public void performSearch() throws SearchServiceException, UIException, SQLException {
queryArgs = prepareDefaultFilters(context, getView(), getAllFilterQueries());
//If we are on a search page performing a search a query may be used
Request request = ObjectModelHelper.getRequest(objectModel);
String scopeString = request.getParameter("scope");
// Are we in a community or collection?
DSpaceObject dso;
if (scopeString == null || "".equals(scopeString))
{
// get the search scope from the url handle
dso = HandleUtil.obtainHandle(objectModel);
}
else
{
// Get the search scope from the location parameter
dso = HandleManager.resolveToObject(context, scopeString);
String query = request.getParameter("query");
if(query != null && !"".equals(query)){
queryArgs.setQuery(query);
}
return dso;
//We do not need to retrieve any dspace objects, only facets
queryArgs.setMaxResults(0);
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
queryResults = getSearchService().search(context, dso, queryArgs);
}
protected SolrQuery prepareDefaultFilters(String scope, String ...filterQueries) {
@Override
public void addOptions(Options options) throws SAXException, WingException, SQLException, IOException, AuthorizeException {
queryArgs = new SolrQuery();
Request request = ObjectModelHelper.getRequest(objectModel);
SearchUtils.SolrFacetConfig[] facets = SearchUtils.getFacetsForType(scope);
try {
performSearch();
}catch (Exception e){
log.error("Error while searching for sidebar facets", e);
return;
}
if (this.queryResults != null) {
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
java.util.List<String> fqs = new ArrayList<String>();
if(request.getParameterValues("fq") != null){
for (int i = 0; i < request.getParameterValues("fq").length; i++) {
String fq = request.getParameterValues("fq")[i];
fqs.add(getSearchService().toFilterQuery(context, fq).getFilterQuery());
}
}
FacetFieldConfig[] facets = SearchUtils.getFacetsForType(getView());
if (facets != null && 0 < facets.length) {
List browse = options.addList("discovery");
browse.setHead(T_FILTER_HEAD);
for (FacetFieldConfig field : facets) {
//Retrieve our values
java.util.List<DiscoverResult.FacetResult> facetValues = queryResults.getFacetResult(field.getField());
int shownFacets = this.queryArgs.getFacetLimit();
//This is needed to make sure that the date filters do not remain empty
if (0 < facetValues.size()) {
Iterator<DiscoverResult.FacetResult> iter = facetValues.iterator();
List filterValsList = browse.addList(field.getField());
filterValsList.setHead(message("xmlui.ArtifactBrowser.AdvancedSearch.type_" + field.getField().replace("_lc", "")));
for (int i = 0; i < shownFacets; i++) {
if (!iter.hasNext())
{
break;
}
DiscoverResult.FacetResult value = iter.next();
if (i < shownFacets - 1) {
String displayedValue = value.getDisplayedValue();
String filterQuery = value.getAsFilterQuery();
if (fqs.contains(filterQuery)) {
filterValsList.addItem(Math.random() + "", "selected").addContent(displayedValue + " (" + value.getCount() + ")");
} else {
String paramsQuery = retrieveParameters(request);
filterValsList.addItem().addXref(
contextPath +
(dso == null ? "" : "/handle/" + dso.getHandle()) +
"/discover?" +
paramsQuery +
"fq=" +
//TODO: encode URLEncoder ?
filterQuery,
displayedValue + " (" + value.getCount() + ")"
);
}
}
//Show a view more url should there be more values, unless we have a date
if (i == shownFacets - 1 && !field.isDate()/*&& facetField.getGap() == null*/) {
addViewMoreUrl(filterValsList, dso, request, field.getField());
}
}
}
}
}
}
}
/**
* Returns the parameters used so it can be used in a url
* @param request the cocoon request
* @return the parameters used on this page
*/
private String retrieveParameters(Request request) {
StringBuffer result = new StringBuffer();
Enumeration keys = request.getParameterNames();
if(keys != null){
while (keys.hasMoreElements()){
String key = (String) keys.nextElement();
//Ignore the page and submit button keys
if(key != null && !"page".equals(key) && !key.startsWith("submit")){
String[] vals = request.getParameterValues(key);
for(String paramValue : vals){
result.append(key).append("=").append(paramValue);
result.append("&");
}
}
}
}
return result.toString();
}
private void addViewMoreUrl(List facet, DSpaceObject dso, Request request, String fieldName) throws WingException {
String parameters = retrieveParameters(request);
facet.addItem().addXref(
contextPath +
(dso == null ? "" : "/handle/" + dso.getHandle()) +
"/search-filter?" + parameters + BrowseFacet.FACET_FIELD + "=" + fieldName,
T_VIEW_MORE
);
}
public DiscoverQuery prepareDefaultFilters(Context context, String scope, String ...filterQueries) {
DiscoverQuery queryArgs = new DiscoverQuery();
FacetFieldConfig[] facets = SearchUtils.getFacetsForType(scope);
log.info("facets for scope, " + scope + ": " + (facets != null ? facets.length : null));
@@ -213,24 +305,24 @@ public abstract class AbstractFiltersTransformer extends AbstractDSpaceTransform
if (facets != null){
queryArgs.setFacetLimit(max);
queryArgs.setFacetMinCount(1);
queryArgs.setFacet(true);
}
//Add the default filters
queryArgs.addFilterQueries(SearchUtils.getDefaultFilters(scope));
queryArgs.addFilterQueries(filterQueries);
/** enable faceting of search results */
if (facets != null){
for (SearchUtils.SolrFacetConfig facet : facets) {
for (FacetFieldConfig facet : facets) {
if(facet.isDate()){
String dateFacet = facet.getFacetField();
String dateFacet = facet.getField();
try{
//Get a range query so we can create facet queries ranging from out first to our last date
//Attempt to determine our oldest & newest year by checking for previously selected filters
int oldestYear = -1;
int newestYear = -1;
for (String filterQuery : filterQueries) {
if(filterQuery.startsWith(facet.getFacetField() + ":")){
if(filterQuery.startsWith(facet.getField() + ":")){
//Check for a range
Pattern pattern = Pattern.compile("\\[(.*? TO .*?)\\]");
Matcher matcher = pattern.matcher(filterQuery);
@@ -264,22 +356,31 @@ public abstract class AbstractFiltersTransformer extends AbstractDSpaceTransform
//Check if we have found a range, if not then retrieve our first & last year by using solr
if(oldestYear == -1 && newestYear == -1){
SolrQuery yearRangeQuery = new SolrQuery();
yearRangeQuery.setRows(1);
DiscoverQuery yearRangeQuery = new DiscoverQuery();
yearRangeQuery.setMaxResults(1);
//Set our query to anything that has this value
yearRangeQuery.setQuery(facet.getFacetField() + ":[* TO *]");
yearRangeQuery.addFieldPresentQueries(facet.getField());
//Set sorting so our last value will appear on top
yearRangeQuery.setSortField(dateFacet, SolrQuery.ORDER.asc);
yearRangeQuery.addFilterQuery(filterQueries);
QueryResponse lastYearResult = getSearchService().search(yearRangeQuery);
if(lastYearResult.getResults() != null && 0 < lastYearResult.getResults().size() && lastYearResult.getResults().get(0).getFieldValue(dateFacet) != null){
oldestYear = (Integer) lastYearResult.getResults().get(0).get(dateFacet);
yearRangeQuery.setSortField(dateFacet, DiscoverQuery.SORT_ORDER.asc);
yearRangeQuery.addFilterQueries(filterQueries);
yearRangeQuery.addSearchField(dateFacet);
DiscoverResult lastYearResult = getSearchService().search(context, yearRangeQuery);
if(0 < lastYearResult.getDspaceObjects().size()){
java.util.List<DiscoverResult.SearchDocument> searchDocuments = lastYearResult.getSearchDocument(lastYearResult.getDspaceObjects().get(0));
if(0 < searchDocuments.size() && 0 < searchDocuments.get(0).getSearchFieldValues(dateFacet).size()){
oldestYear = Integer.parseInt(searchDocuments.get(0).getSearchFieldValues(dateFacet).get(0));
}
}
//Now get the first year
yearRangeQuery.setSortField(dateFacet, SolrQuery.ORDER.desc);
QueryResponse firstYearResult = getSearchService().search(yearRangeQuery);
if(firstYearResult.getResults() != null && 0 < firstYearResult.getResults().size() && firstYearResult.getResults().get(0).getFieldValue(dateFacet) != null){
newestYear = (Integer) firstYearResult.getResults().get(0).get(dateFacet);
yearRangeQuery.setSortField(dateFacet, DiscoverQuery.SORT_ORDER.desc);
DiscoverResult firstYearResult = getSearchService().search(context, yearRangeQuery);
if( 0 < firstYearResult.getDspaceObjects().size()){
java.util.List<DiscoverResult.SearchDocument> searchDocuments = firstYearResult.getSearchDocument(firstYearResult.getDspaceObjects().get(0));
if(0 < searchDocuments.size() && 0 < searchDocuments.get(0).getSearchFieldValues(dateFacet).size()){
newestYear = Integer.parseInt(searchDocuments.get(0).getSearchFieldValues(dateFacet).get(0));
}
}
//No values found!
if(newestYear == -1 || oldestYear == -1)
@@ -305,7 +406,7 @@ public abstract class AbstractFiltersTransformer extends AbstractDSpaceTransform
//We need a list of our years
//We have a date range add faceting for our field
//The faceting will automatically be limited to the 10 years in our span due to our filterquery
queryArgs.addFacetField(facet.getFacetField());
queryArgs.addFacetField(facet);
}else{
java.util.List<String> facetQueries = new ArrayList<String>();
//Create facet queries but limit then to 11 (11 == when we need to show a show more url)
@@ -338,201 +439,79 @@ public abstract class AbstractFiltersTransformer extends AbstractDSpaceTransform
}catch (Exception e){
log.error(LogManager.getHeader(context, "Error in discovery while setting up date facet range", "date facet: " + dateFacet), e);
}
}else{
queryArgs.addFacetField(facet.getFacetField());
queryArgs.addFacetField(facet);
}
}
}
//Add the default filters
queryArgs.addFilterQuery(SearchUtils.getDefaultFilters(scope));
return queryArgs;
}
@Override
public void addOptions(Options options) throws SAXException, WingException, UIException, SQLException, IOException, AuthorizeException {
Request request = ObjectModelHelper.getRequest(objectModel);
public String getView() throws SQLException {
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
java.util.List<String> fqs = Arrays.asList(request.getParameterValues("fq") != null ? request.getParameterValues("fq") : new String[0]);
if (this.queryResults != null) {
SearchUtils.SolrFacetConfig[] facets = SearchUtils.getFacetsForType(getView());
if (facets != null && 0 < facets.length) {
List browse = options.addList("discovery");
browse.setHead(T_FILTER_HEAD);
for (SearchUtils.SolrFacetConfig field : facets) {
//Retrieve our values
java.util.List<FilterDisplayValue> values = new ArrayList<FilterDisplayValue>();
int shownFacets = this.queryArgs.getFacetLimit();
FacetField facet = queryResults.getFacetField(field.getFacetField());
if(facet != null){
java.util.List<FacetField.Count> facetVals = facet.getValues();
if(facetVals == null)
{
continue;
}
for (FacetField.Count count : facetVals) {
values.add(new FilterDisplayValue(SearchUtils.getFilterQueryDisplay(count.getName()), count.getCount(), count.getAsFilterQuery()));
}
}
if(field.isDate()){
if(0 < values.size()){
//Check for values comming from a facet field.
//If we have values we need to sort these & get the newest ones on top
//There is no other way for this since solr doesn't support facet sorting
TreeMap<String, FilterDisplayValue> sortedVals = new TreeMap<String, FilterDisplayValue>(Collections.reverseOrder());
for (FilterDisplayValue filterDisplayValue : values) {
//No need to show empty years
if(0 < filterDisplayValue.getCount())
{
sortedVals.put(filterDisplayValue.getDisplayedVal(), filterDisplayValue);
}
}
//Make sure we retrieve our sorted values
values = Arrays.asList(sortedVals.values().toArray(new FilterDisplayValue[sortedVals.size()]));
}else{
//Attempt to retrieve it as a facet query
//Since our facet query result is returned as a hashmap we need to sort it by using a treemap
TreeMap<String, Integer> sortedFacetQueries = new TreeMap<String, Integer>(queryResults.getFacetQuery());
for(String facetQuery : sortedFacetQueries.descendingKeySet()){
if(facetQuery != null && facetQuery.startsWith(field.getFacetField())){
//We have a facet query, the values looks something like: dateissued.year:[1990 TO 2000] AND -2000
//Prepare the string from {facet.field.name}:[startyear TO endyear] to startyear - endyear
String name = facetQuery.substring(facetQuery.indexOf('[') + 1);
name = name.substring(0, name.lastIndexOf(']')).replaceAll("TO", "-");
Integer count = sortedFacetQueries.get(facetQuery);
//No need to show empty years
if(0 < count)
{
values.add(new FilterDisplayValue(name, count, facetQuery));
}
}
}
}
}
//This is needed to make sure that the date filters do not remain empty
if (0 < values.size()) {
Iterator<FilterDisplayValue> iter = values.iterator();
List filterValsList = browse.addList(field.getFacetField());
filterValsList.setHead(message("xmlui.ArtifactBrowser.AdvancedSearch.type_" + field.getFacetField().replace("_lc", "")));
for (int i = 0; i < shownFacets; i++) {
if (!iter.hasNext())
{
break;
}
FilterDisplayValue value = iter.next();
if (i < shownFacets - 1) {
String displayedValue = value.getDisplayedVal();
String filterQuery = value.getAsFilterQuery();
if (field.getFacetField().equals("location.comm") || field.getFacetField().equals("location.coll")) {
//We have a community/collection, resolve it to a dspaceObject
displayedValue = SolrServiceImpl.locationToName(context, field.getFacetField(), displayedValue);
}
if (fqs.contains(filterQuery)) {
filterValsList.addItem(Math.random() + "", "selected").addContent(displayedValue + " (" + value.getCount() + ")");
} else {
String paramsQuery = "";
Enumeration keys = request.getParameterNames();
if(keys != null){
while (keys.hasMoreElements()){
String key = (String) keys.nextElement();
if(key != null && !"page".equals(key)){
String[] vals = request.getParameterValues(key);
for(String paramValue : vals){
paramsQuery += key + "=" + paramValue;
paramsQuery += "&";
}
}
}
}
filterValsList.addItem().addXref(
contextPath +
(dso == null ? "" : "/handle/" + dso.getHandle()) +
"/discover?" +
paramsQuery +
"fq=" +
filterQuery,
displayedValue + " (" + value.getCount() + ")"
);
}
}
//Show a view more url should there be more values, unless we have a date
if (i == shownFacets - 1 && !field.isDate()/*&& facetField.getGap() == null*/) {
addViewMoreUrl(filterValsList, dso, request, field.getFacetField());
}
}
}
}
if(dso == null){
if("discover".equals(ObjectModelHelper.getRequest(objectModel).getSitemapURI())){
//We are on a search page
return "search";
}else{
return "site";
}
}else
if(dso instanceof Community){
return "community";
}else
if(dso instanceof org.dspace.content.Collection){
return "collection";
}else
if(dso instanceof Item){
return "item";
}
return null;
}
/**
* Returns all the filter queries for use by discovery
* This method returns more expanded filter queries then the getParameterFilterQueries
* @return an array containing the filter queries
*/
protected String[] getAllFilterQueries() {
try {
java.util.List<String> allFilterQueries = new ArrayList<String>();
Request request = ObjectModelHelper.getRequest(objectModel);
java.util.List<String> fqs = new ArrayList<String>();
if(request.getParameterValues("fq") != null)
{
fqs.addAll(Arrays.asList(request.getParameterValues("fq")));
}
String type = request.getParameter("filtertype");
String value = request.getParameter("filter");
if(value != null && !value.equals("") && request.getParameter("submit_search-filter-controls_add") != null){
allFilterQueries.add(getSearchService().toFilterQuery(context, (type.equals("*") ? "" : type), value).getFilterQuery());
}
//Add all the previous filters also
for (String fq : fqs) {
allFilterQueries.add(getSearchService().toFilterQuery(context, fq).getFilterQuery());
}
return allFilterQueries.toArray(new String[allFilterQueries.size()]);
}
catch (RuntimeException re) {
throw re;
} catch (Exception e) {
return null;
}
}
private void addViewMoreUrl(List facet, DSpaceObject dso, Request request, String fieldName) throws WingException {
facet.addItem().addXref(
contextPath +
(dso == null ? "" : "/handle/" + dso.getHandle()) +
"/search-filter?" + BrowseFacet.FACET_FIELD + "=" + fieldName +
(request.getQueryString() != null ? "&" + request.getQueryString() : ""),
T_VIEW_MORE
);
}
@Override
public void recycle() {
queryResults = null;
queryArgs = null;
}
private static final class FilterDisplayValue {
private String asFilterQuery;
private String displayedVal;
private long count;
private FilterDisplayValue(String displayedVal, long count, String asFilterQuery) {
this.asFilterQuery = asFilterQuery;
this.displayedVal = displayedVal;
this.count = count;
}
public String getDisplayedVal() {
return displayedVal;
}
public long getCount() {
return count;
}
public String getAsFilterQuery(){
return asFilterQuery;
}
validity = null;
super.recycle();
}
}

View File

@@ -10,7 +10,6 @@ package org.dspace.app.xmlui.aspect.discovery;
import java.io.IOException;
import java.sql.SQLException;
import java.util.*;
import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -27,10 +26,12 @@ import org.dspace.app.xmlui.wing.element.List;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.*;
import org.dspace.core.ConfigurationManager;
import org.dspace.discovery.DiscoverFilterQuery;
import org.dspace.discovery.SearchService;
import org.dspace.discovery.SearchUtils;
import org.dspace.utils.DSpace;
import org.xml.sax.SAXException;
import org.dspace.discovery.SearchServiceException;
import org.dspace.discovery.SolrServiceImpl;
/**
* Preform a simple search of the repository. The user provides a simple one
@@ -65,6 +66,14 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC
private static final Message T_FILTER_HEAD = message("xmlui.Discovery.SimpleSearch.filter_head");
private static final Message T_FILTERS_SELECTED = message("xmlui.ArtifactBrowser.SimpleSearch.filter.selected");
private SearchService searchService = null;
public SimpleSearch() {
DSpace dspace = new DSpace();
searchService = dspace.getServiceManager().getServiceByName(SearchService.class.getName(),SearchService.class);
}
/**
* Add Page metadata.
*/
@@ -73,7 +82,7 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC
pageMeta.addTrailLink(contextPath + "/", T_dspace_home);
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
if ((dso instanceof Collection) || (dso instanceof Community)) {
if ((dso instanceof org.dspace.content.Collection) || (dso instanceof Community)) {
HandleUtil.buildHandleTrail(dso, pageMeta, contextPath);
}
@@ -97,9 +106,9 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC
// String searchUrl = SearchUtils.getConfig().getString("solr.search.server");
// if(searchUrl != null && !searchUrl.endsWith("/"))
// searchUrl += "/";
String searchUrl = ConfigurationManager.getProperty("dspace.url") + "/JSON/discovery/searchSolr";
String searchUrl = ConfigurationManager.getProperty("dspace.url") + "/JSON/discovery/search";
search.addHidden("solr-search-url").setValue(searchUrl);
search.addHidden("discovery-json-search-url").setValue(searchUrl);
search.addHidden("contextpath").setValue(contextPath);
String[] fqs = getParameterFilterQueries();
@@ -132,47 +141,26 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC
CheckBox box = composite.addCheckBox("fq");
for(String name : fqs){
for(String filterQuery : fqs){
//for(Map.Entry<String, Integer> filter : filters.entrySet()){
//String name = filter.getKey();
//long count = filter.getValue();
DiscoverFilterQuery fq = searchService.toFilterQuery(context, filterQuery);
String field = name;
String value = name;
if(name.contains(":"))
{
field = name.split(":")[0];
value = name.split(":")[1];
}else{
//We have got no field, so we are using everything
field = "*";
}
value = value.replace("\\", "");
if("*".equals(field))
{
Option option = box.addOption(true,fq.getFilterQuery());
String field = fq.getField();
//If no field specified, then all is used.
if(field == null || field.equals("") || field.equals("*") || field.equals("all_ac")){
field = "all";
}
if(name.startsWith("*:"))
{
name = name.substring(name.indexOf(":") + 1, name.length());
}
Option option = box.addOption(true,name);
option.addContent(message("xmlui.ArtifactBrowser.SimpleSearch.filter." + field));
if(field.equals("location.comm") || field.equals("location.coll")){
//We have a community/collection, resolve it to a dspaceObject
value = SolrServiceImpl.locationToName(context, field, value);
} else
if(field.endsWith("_filter")){
value = SearchUtils.getFilterQueryDisplay(value);
}
//We have a filter query get the display value
//Check for a range query
Pattern pattern = Pattern.compile("\\[(.*? TO .*?)\\]");
Matcher matcher = pattern.matcher(value);
Matcher matcher = pattern.matcher(fq.getDisplayedValue());
boolean hasPattern = matcher.find();
if(hasPattern){
String[] years = matcher.group(0).replace("[", "").replace("]", "").split(" TO ");
@@ -180,9 +168,7 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC
continue;
}
option.addContent(": " + value);
option.addContent(": " + fq.getDisplayedValue());
}
}
@@ -199,7 +185,7 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC
Select select = filterComp.addSelect("filtertype");
//First of all add a default filter
select.addOption("*", message("xmlui.ArtifactBrowser.SimpleSearch.filter.all"));
select.addOption("all_ac", message("xmlui.ArtifactBrowser.SimpleSearch.filter.all"));
//For each field found (at least one) add options
for (String field : filterFields) {
@@ -246,17 +232,17 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC
//Have we added a filter using the UI
if(request.getParameter("filter") != null && !"".equals(request.getParameter("filter")) && request.getParameter("submit_search-filter-controls_add") != null)
{
fqs.add((request.getParameter("filtertype").equals("*") ? "" : request.getParameter("filtertype") + ":") + request.getParameter("filter"));
fqs.add((request.getParameter("filtertype")) + ":" + request.getParameter("filter"));
}
return fqs.toArray(new String[fqs.size()]);
}
/**
* Returns all the filter queries for use by solr
* Returns all the filter queries for use by discovery
* This method returns more expanded filter queries then the getParameterFilterQueries
* @return an array containing the filter queries
*/
protected String[] getSolrFilterQueries() {
protected String[] getFilterQueries() {
try {
java.util.List<String> allFilterQueries = new ArrayList<String>();
Request request = ObjectModelHelper.getRequest(objectModel);
@@ -271,20 +257,12 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC
String value = request.getParameter("filter");
if(value != null && !value.equals("") && request.getParameter("submit_search-filter-controls_add") != null){
String exactFq = (type.equals("*") ? "" : type + ":") + value;
fqs.add(exactFq + " OR " + exactFq + "*");
allFilterQueries.add(searchService.toFilterQuery(context, (type.equals("*") ? "" : type), value).getFilterQuery());
}
//Add all the previous filters also
for (String fq : fqs) {
//Do not put a wildcard after a range query
if (fq.matches(".*\\:\\[.* TO .*\\](?![a-z 0-9]).*")) {
allFilterQueries.add(fq);
}
else
{
allFilterQueries.add(fq.endsWith("*") ? fq : fq + " OR " + fq + "*");
}
allFilterQueries.add(searchService.toFilterQuery(context, fq).getFilterQuery());
}
return allFilterQueries.toArray(new String[allFilterQueries.size()]);

View File

@@ -7,10 +7,6 @@
*/
package org.dspace.app.xmlui.aspect.discovery;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.common.SolrDocument;
import org.dspace.app.xmlui.utils.UIException;
import org.dspace.app.xmlui.wing.Message;
import org.dspace.app.xmlui.wing.WingException;
import org.dspace.app.xmlui.wing.element.Body;
@@ -18,25 +14,19 @@ import org.dspace.app.xmlui.wing.element.Division;
import org.dspace.app.xmlui.wing.element.ReferenceSet;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject;
import org.dspace.core.Constants;
import org.dspace.discovery.SearchService;
import org.dspace.discovery.SearchServiceException;
import org.dspace.discovery.SearchUtils;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.sql.SQLException;
/**
* Transformer that displays the recently submitted items on the dspace home page
* Renders a list of recently submitted items for the homepage by using discovery
*
* @author Kevin Van de Velde (kevin at atmire dot com)
* @author Mark Diggory (markd at atmire dot com)
* @author Ben Bosman (ben at atmire dot com)
*/
public class SiteRecentSubmissions extends AbstractFiltersTransformer {
private static final Logger log = Logger.getLogger(SiteRecentSubmissions.class);
public class SiteRecentSubmissions extends AbstractRecentSubmissionTransformer {
private static final Message T_head_recent_submissions =
message("xmlui.ArtifactBrowser.SiteViewer.head_recent_submissions");
@@ -47,12 +37,13 @@ public class SiteRecentSubmissions extends AbstractFiltersTransformer {
* collections)
*/
public void addBody(Body body) throws SAXException, WingException,
UIException, SQLException, IOException, AuthorizeException {
SQLException, IOException, AuthorizeException {
try {
performSearch(null);
} catch (SearchServiceException e) {
log.error(e.getMessage(), e);
getRecentlySubmittedItems(null);
//Only attempt to render our result if we have one.
if (queryResults == null) {
return;
}
Division home = body.addDivision("site-home", "primary repository");
@@ -66,53 +57,14 @@ public class SiteRecentSubmissions extends AbstractFiltersTransformer {
"site-last-submitted", ReferenceSet.TYPE_SUMMARY_LIST,
null, "recent-submissions");
if (queryResults != null) {
for (SolrDocument doc : queryResults.getResults()) {
DSpaceObject obj = SearchUtils.findDSpaceObject(context, doc);
if(obj != null)
{
lastSubmitted.addReference(obj);
}
}
for (DSpaceObject dso : queryResults.getDspaceObjects()) {
lastSubmitted.addReference(dso);
}
}
public String getView()
{
return "site";
}
/**
* facet.limit=11&wt=javabin&rows=5&sort=dateaccessioned+asc&facet=true&facet.mincount=1&q=search.resourcetype:2&version=1
*
* @param object
*/
@Override
public void performSearch(DSpaceObject object) throws SearchServiceException, UIException {
if(queryResults != null)
{
return; // queryResults;
}
queryArgs = prepareDefaultFilters(getView());
queryArgs.setQuery("search.resourcetype:" + Constants.ITEM);
queryArgs.setRows(SearchUtils.getConfig().getInt("solr.recent-submissions.size", 5));
String sortField = SearchUtils.getConfig().getString("recent.submissions.sort-option");
if(sortField != null){
queryArgs.setSortField(
sortField,
SolrQuery.ORDER.desc
);
}
SearchService service = getSearchService();
queryResults = service.search(queryArgs);
}
}

View File

@@ -0,0 +1,134 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.xmlui.aspect.discovery.json;
import org.apache.avalon.excalibur.pool.Recyclable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.Response;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.reading.AbstractReader;
import org.apache.log4j.Logger;
import org.dspace.discovery.*;
import org.dspace.utils.DSpace;
import org.xml.sax.SAXException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Map;
/**
* Class used to search in the discovery backend and return a json formatted string
*
* @author Kevin Van de Velde (kevin at atmire dot com)
* @author Mark Diggory (markd at atmire dot com)
* @author Ben Bosman (ben at atmire dot com)
*/
public class JSONDiscoverySearcher extends AbstractReader implements Recyclable {
private static Logger log = Logger.getLogger(JSONDiscoverySearcher.class);
/** These are all our parameters which can be used by this generator **/
private DiscoverQuery queryArgs;
private String jsonWrf;
/** The Cocoon response */
protected Response response;
protected SearchService getSearchService()
{
DSpace dspace = new DSpace();
org.dspace.kernel.ServiceManager manager = dspace.getServiceManager() ;
return manager.getServiceByName(SearchService.class.getName(),SearchService.class);
}
@Override
public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par) throws ProcessingException, SAXException, IOException {
//Retrieve all the given parameters
Request request = ObjectModelHelper.getRequest(objectModel);
this.response = ObjectModelHelper.getResponse(objectModel);
queryArgs = new DiscoverQuery();
queryArgs.setQuery(request.getParameter("q"));
//Retrieve all our filter queries
if(request.getParameterValues("fq") != null)
queryArgs.addFilterQueries(request.getParameterValues("fq"));
//Retrieve our facet fields
if(request.getParameterValues("facet.field") != null){
for (int i = 0; i < request.getParameterValues("facet.field").length; i++) {
String facetField = request.getParameterValues("facet.field")[i];
queryArgs.addFacetField(new FacetFieldConfig(facetField, false));
}
}
//Retrieve our facet limit (if any)
int facetLimit;
if(request.getParameter("facet.limit") != null){
try{
facetLimit = Integer.parseInt(request.getParameter("facet.limit"));
}catch (Exception e){
//Should an invalid value be supplied use -1
facetLimit = -1;
}
}
else
{
facetLimit = -1;
}
queryArgs.setFacetLimit(facetLimit);
//Retrieve our sorting value
String facetSort = request.getParameter("facet.sort");
if(facetSort == null || facetSort.equalsIgnoreCase("count"))
queryArgs.setFacetSort(DiscoverQuery.FACET_SORT.COUNT);
else
queryArgs.setFacetSort(DiscoverQuery.FACET_SORT.INDEX);
//Retrieve our facet min count
int facetMinCount;
try{
facetMinCount = Integer.parseInt(request.getParameter("facet.mincount"));
}catch (Exception e){
facetMinCount = 1;
}
queryArgs.setFacetMinCount(facetMinCount);
jsonWrf = request.getParameter("json.wrf");
}
public void generate() throws IOException, SAXException, ProcessingException {
String result = null;
try {
result = getSearchService().searchJSON(queryArgs, jsonWrf);
} catch (SearchServiceException e) {
log.error("Error while retrieving JSON string for Discovery auto complete", e);
}
if(result != null){
ByteArrayInputStream inputStream = new ByteArrayInputStream(result.getBytes("UTF-8"));
byte[] buffer = new byte[8192];
response.setHeader("Content-Length", String.valueOf(result.length()));
int length;
while ((length = inputStream.read(buffer)) > -1)
{
out.write(buffer, 0, length);
}
out.flush();
}
}
}

View File

@@ -1,238 +0,0 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.xmlui.aspect.discovery.json;
import org.apache.avalon.excalibur.pool.Recyclable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.Response;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.reading.AbstractReader;
import org.apache.commons.collections.ExtendedProperties;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.log4j.Logger;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.FacetParams;
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
import org.dspace.constants.Constants;
import org.dspace.core.ConfigurationManager;
import org.dspace.discovery.SolrServiceImpl;
import org.xml.sax.SAXException;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
/**
* Class used to search in solr and return a json formatted string
*
* @author Kevin Van de Velde (kevin at atmire dot com)
* @author Mark Diggory (markd at atmire dot com)
* @author Ben Bosman (ben at atmire dot com)
*/
public class JSONSolrSearcher extends AbstractReader implements Recyclable {
private static Logger log = Logger.getLogger(JSONSolrSearcher.class);
/** These are all our parameters which can be used by this generator **/
private String query;
private String[] filterQueries;
private String[] facetFields;
private int facetLimit;
private String facetSort;
private int facetMinCount;
private String solrServerUrl;
private String jsonWrf;
/** The Cocoon response */
protected Response response;
@Override
public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par) throws ProcessingException, SAXException, IOException {
//Retrieve all the given parameters
Request request = ObjectModelHelper.getRequest(objectModel);
this.response = ObjectModelHelper.getResponse(objectModel);
query = request.getParameter(CommonParams.Q);
if(query == null)
{
query = "*:*";
}
//Retrieve all our filter queries
filterQueries = request.getParameterValues(CommonParams.FQ);
//Retrieve our facet fields
facetFields = request.getParameterValues(FacetParams.FACET_FIELD);
//Retrieve our facet limit (if any)
if(request.getParameter(FacetParams.FACET_LIMIT) != null){
try{
facetLimit = Integer.parseInt(request.getParameter(FacetParams.FACET_LIMIT));
}catch (Exception e){
//Should an invalid value be supplied use -1
facetLimit = -1;
}
}
else
{
facetLimit = -1;
}
//Retrieve our sorting value
facetSort = request.getParameter(FacetParams.FACET_SORT);
//Make sure we have a valid sorting value
if(!FacetParams.FACET_SORT_INDEX.equals(facetSort) && !FacetParams.FACET_SORT_COUNT.equals(facetSort))
{
facetSort = null;
}
//Retrieve our facet min count
facetMinCount = 1;
try{
facetMinCount = Integer.parseInt(request.getParameter(FacetParams.FACET_MINCOUNT));
}catch (Exception e){
facetMinCount = 1;
}
jsonWrf = request.getParameter("json.wrf");
//Retrieve our discovery solr path
ExtendedProperties props = null;
//Method that will retrieve all the possible configs we have
props = ExtendedProperties.convertProperties(ConfigurationManager.getProperties());
InputStream is = null;
try {
File config = new File(props.getProperty("dspace.dir") + "/config/dspace-solr-search.cfg");
if (config.exists()) {
props.combine(new ExtendedProperties(config.getAbsolutePath()));
} else {
is = SolrServiceImpl.class.getResourceAsStream("dspace-solr-search.cfg");
ExtendedProperties defaults = new ExtendedProperties();
defaults.load(is);
props.combine(defaults);
}
}
catch (Exception e) {
log.error("Error while retrieving solr url", e);
e.printStackTrace();
}
finally {
if (is != null) {
is.close();
}
}
if(props.getProperty("solr.search.server") != null)
{
this.solrServerUrl = props.getProperty("solr.search.server").toString();
}
}
public void generate() throws IOException, SAXException, ProcessingException {
if(solrServerUrl == null)
{
return;
}
Map<String, String> params = new HashMap<String, String>();
String solrRequestUrl = solrServerUrl + "/select";
//Add our default parameters
params.put(CommonParams.ROWS, "0");
params.put(CommonParams.WT, "json");
//We uwe json as out output type
params.put("json.nl", "map");
params.put("json.wrf", jsonWrf);
params.put(FacetParams.FACET, Boolean.TRUE.toString());
//Generate our json out of the given params
try
{
params.put(CommonParams.Q, URLEncoder.encode(query, Constants.DEFAULT_ENCODING));
}
catch (UnsupportedEncodingException uee)
{
//Should never occur
return;
}
params.put(FacetParams.FACET_LIMIT, String.valueOf(facetLimit));
if(facetSort != null)
{
params.put(FacetParams.FACET_SORT, facetSort);
}
params.put(FacetParams.FACET_MINCOUNT, String.valueOf(facetMinCount));
solrRequestUrl = AbstractDSpaceTransformer.generateURL(solrRequestUrl, params);
if (facetFields != null || filterQueries != null) {
StringBuilder urlBuilder = new StringBuilder(solrRequestUrl);
if(facetFields != null){
//Add our facet fields
for (String facetField : facetFields) {
urlBuilder.append("&").append(FacetParams.FACET_FIELD).append("=");
//This class can only be used for autocomplete facet fields
if(!facetField.endsWith(".year") && !facetField.endsWith("_ac"))
{
urlBuilder.append(URLEncoder.encode(facetField + "_ac", Constants.DEFAULT_ENCODING));
}
else
{
urlBuilder.append(URLEncoder.encode(facetField, Constants.DEFAULT_ENCODING));
}
}
}
if(filterQueries != null){
for (String filterQuery : filterQueries) {
urlBuilder.append("&").append(CommonParams.FQ).append("=").append(URLEncoder.encode(filterQuery, Constants.DEFAULT_ENCODING));
}
}
solrRequestUrl = urlBuilder.toString();
}
try {
GetMethod get = new GetMethod(solrRequestUrl);
new HttpClient().executeMethod(get);
String result = get.getResponseBodyAsString();
if(result != null){
ByteArrayInputStream inputStream = new ByteArrayInputStream(result.getBytes("UTF-8"));
byte[] buffer = new byte[8192];
response.setHeader("Content-Length", String.valueOf(result.length()));
int length;
while ((length = inputStream.read(buffer)) > -1)
{
out.write(buffer, 0, length);
}
out.flush();
}
} catch (Exception e) {
log.error("Error while getting json solr result for discovery search recommendation", e);
e.printStackTrace();
}
}
}

View File

@@ -58,6 +58,7 @@ and searching the repository.
<map:transformer name="SearchFacetFilter" src="org.dspace.app.xmlui.aspect.discovery.SearchFacetFilter"/>
<map:transformer name="FrontPageSearch" src="org.dspace.app.xmlui.aspect.discovery.SiteViewer"/>
<map:transformer name="SiteRecentSubmissions" src="org.dspace.app.xmlui.aspect.discovery.SiteRecentSubmissions"/>
<map:transformer name="SidebarFacetsTransformer" src="org.dspace.app.xmlui.aspect.discovery.SidebarFacetsTransformer"/>
<map:transformer name="CommunitySearch" src="org.dspace.app.xmlui.aspect.discovery.CommunitySearch"/>
@@ -69,7 +70,6 @@ and searching the repository.
<map:transformer name="RelatedItems" src="org.dspace.app.xmlui.aspect.discovery.RelatedItems"/>
<map:transformer name="ItemFacets" src="org.dspace.app.xmlui.aspect.discovery.ItemFacets"/>
</map:transformers>
@@ -105,6 +105,7 @@ and searching the repository.
along with a list of top level communities in DSpace.
-->
<map:match pattern="">
<map:transform type="SidebarFacetsTransformer"/>
<map:transform type="FrontPageSearch"/>
<map:transform type="SiteRecentSubmissions"/>
@@ -124,7 +125,8 @@ and searching the repository.
<!-- Search -->
<map:match pattern="discover">
<map:transform type="SimpleSearch"/>
<map:transform type="SidebarFacetsTransformer"/>
<map:transform type="SimpleSearch"/>
<map:transform type="IncludePageMeta">
<map:parameter name="stylesheet.screen.discovery#1" value="../../static/css/discovery/style.css"/>
@@ -143,11 +145,6 @@ and searching the repository.
<map:serialize type="xml"/>
</map:match>
<!--<map:match pattern="simple-search">-->
<!--<map:transform type="SimpleSearch"/>-->
<!--<map:serialize type="xml"/>-->
<!--</map:match>-->
<!--<map:match pattern="browse-discovery">-->
<!--<map:transform type="BrowseFacet"/>-->
<!--<map:serialize type="xml"/>-->
@@ -158,13 +155,6 @@ and searching the repository.
<map:serialize type="xml"/>
</map:match>
<!--
<map:match pattern="advanced-search">
<map:transform type="AdvancedSearch"/>
<map:serialize type="xml"/>
</map:match>
-->
<!-- Handle specific features -->
<map:match pattern="handle/*/**">
@@ -180,7 +170,8 @@ and searching the repository.
<!-- Simple search -->
<map:match pattern="handle/*/*/discover">
<map:transform type="SimpleSearch"/>
<map:transform type="SidebarFacetsTransformer"/>
<map:transform type="SimpleSearch"/>
<map:transform type="IncludePageMeta">
<map:parameter name="stylesheet.screen.discovery#1" value="../../static/css/discovery/style.css"/>
@@ -204,35 +195,26 @@ and searching the repository.
<map:transform type="SearchFacetFilter"/>
<map:serialize type="xml"/>
</map:match>
<!-- Simple search again, but this time they said it -->
<!--<map:match pattern="handle/*/*/simple-discover">-->
<!--<map:transform type="SimpleSearch"/>-->
<!--<map:serialize type="xml"/>-->
<!--</map:match>-->
<!-- Advanced search
<map:match pattern="handle/*/*/advanced-search">
<map:transform type="AdvancedSearch"/>
<map:serialize type="xml"/>
</map:match>
-->
</map:match>
</map:match>
<map:match pattern="handle/*/*">
<map:match type="HandleAuthorizedMatcher" pattern="READ">
<map:match type="HandleTypeMatcher" pattern="community">
<map:transform type="SidebarFacetsTransformer"/>
<map:transform type="CommunitySearch"/>
<map:transform type="CommunityRecentSubmissions"/>
<map:serialize type="xml"/>
</map:match>
<map:match type="HandleTypeMatcher" pattern="collection">
<map:transform type="SidebarFacetsTransformer"/>
<map:transform type="CollectionSearch"/>
<map:transform type="CollectionRecentSubmissions"/>
<map:serialize type="xml"/>
</map:match>
<map:match type="HandleTypeMatcher" pattern="item">
<map:transform type="ItemFacets"/>
<!--<map:transform type="SidebarFacetsTransformer"/>-->
<!--<map:transform type="ItemFacets"/>-->
<map:transform type="RelatedItems"/>
<map:serialize type="xml"/>
</map:match>

View File

@@ -6,7 +6,7 @@
<map:components>
<map:readers>
<map:reader name="JSONSolrSearcher" src="org.dspace.app.xmlui.aspect.discovery.json.JSONSolrSearcher"/>
<map:reader name="JSONDiscoverySearcher" src="org.dspace.app.xmlui.aspect.discovery.json.JSONDiscoverySearcher"/>
</map:readers>
<map:serializers>
@@ -19,8 +19,8 @@
<map:pipeline>
<map:match pattern="**">
<map:match pattern="searchSolr">
<map:read type="JSONSolrSearcher" />
<map:match pattern="search">
<map:read type="JSONDiscoverySearcher" />
</map:match>
@@ -31,4 +31,4 @@
</map:pipeline>
</map:pipelines>
</map:sitemap>
</map:sitemap>

View File

@@ -11,7 +11,7 @@ var defaultFacets = new Array();
(function ($) {
$(function () {
var searchUrl = $("input[name='solr-search-url']").val();
var searchUrl = $("input[name='discovery-json-search-url']").val();
Manager = new AjaxSolr.Manager({
solrUrl: searchUrl
});
@@ -82,9 +82,9 @@ var defaultFacets = new Array();
if($(this).val() != '*'){
var facetVal = $(this).val();
//Only facet on autocomplete fields
if(!facetVal.match(/.year$/)){
facetVal += '_ac';
}
// if(!facetVal.match(/.year$/)){
// facetVal += '_ac';
// }
facetFields = [facetVal];
} else {
facetFields = defaultFacets;

View File

@@ -17,8 +17,7 @@ AjaxSolr.AutocompleteWidget = AjaxSolr.AbstractFacetWidget.extend({
var callback = function (response) {
var list = [];
for (var i = 0; i < self.fields.length; i++) {
var field = self.fields[i];
for (var field in response.facet_counts.facet_fields) {
for (var facet in response.facet_counts.facet_fields[field]) {
list.push({
field: field,

View File

@@ -16,6 +16,7 @@
<modules>
<module>dspace-discovery-provider</module>
<module>dspace-discovery-solr</module>
<module>dspace-discovery-xmlui-api</module>
<module>dspace-discovery-xmlui-webapp</module>
</modules>

View File

@@ -10,6 +10,7 @@ solr.facets.search=dc.contributor.author,dc.subject,dc.date.issued_dt
solr.facets.site=dc.contributor.author,dc.subject,dc.date.issued_dt
solr.facets.community=dc.contributor.author,dc.subject,dc.date.issued_dt
solr.facets.collection=dc.contributor.author,dc.subject,dc.date.issued_dt
#Item facets are not supported at the moment
# solr.facets.item=dc.contributor.author,dc.subject,dc.date.issued_dt
@@ -30,7 +31,7 @@ solr.facets.collection=dc.contributor.author,dc.subject,dc.date.issued_dt
#solr.browse.default.filterQuery=
# The filters which can be selected in the search form
solr.search.filters=dc.title, dc.contributor.author, dc.subject, dc.date.issued.year
solr.search.filters=dc.title, dc.contributor.author:full, dc.subject:full, dc.date.issued.year
# Indexed fields which can sorted on in our search
solr.search.sort=dc.title, dc.date.issued_dt
@@ -46,4 +47,4 @@ solr.recent-submissions.size=5
recent.submissions.sort-option=dc.date.accessioned_dt
#Use the property below to limit the number of facet filters in the side of the search page
#search.facet.max=10
#search.facet.max=10

View File

@@ -140,6 +140,12 @@
<type>war</type>
</dependency>
<dependency>
<groupId>org.dspace</groupId>
<artifactId>dspace-discovery-solr</artifactId>
<version>1.8.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.dspace</groupId>
<artifactId>dspace-discovery-xmlui-api</artifactId>
@@ -169,4 +175,4 @@
</dependencies>
</project>
</project>

View File

@@ -555,10 +555,14 @@
<groupId>org.dspace</groupId>
<artifactId>dspace-discovery-provider</artifactId>
</dependency>
<dependency>
<groupId>org.dspace</groupId>
<artifactId>dspace-discovery-solr</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</dependency>
</dependencies>
</project>
</project>

View File

@@ -475,6 +475,20 @@
</analyzer>
</fieldType>
<!--This field is used for auto complete features in the discovery search-->
<fieldType name="dspaceAutoCompleteFull" class="solr.TextField" sortMissingLast="true" omitNorms="true">
<analyzer>
<!--Split everything up by space-->
<tokenizer class="solr.KeywordTokenizerFactory"/>
<!--Lower cases our values-->
<filter class="solr.LowerCaseFilterFactory" />
<!-- The TrimFilter removes any leading or trailing whitespace -->
<filter class="solr.TrimFilterFactory" />
</analyzer>
</fieldType>
<fieldType name="dspaceFilter" class="solr.TextField" sortMissingLast="true" omitNorms="true">
<analyzer>
<!--Treats the entire field as a single token, regardless of its content-->
@@ -546,6 +560,7 @@
<!--Dynamic field used for search autocompletion-->
<dynamicField name="*_ac" type="dspaceAutoComplete" indexed="true" stored="true" omitNorms="true" multiValued="true"/>
<dynamicField name="*_ac.full" type="dspaceAutoCompleteFull" indexed="true" stored="true" omitNorms="true" multiValued="true"/>
<!--Dynamic field used for sidebar filters-->
<dynamicField name="*_filter" type="dspaceFilter" indexed="true" stored="true" multiValued="true" omitNorms="true" />

View File

@@ -281,6 +281,11 @@
<artifactId>dspace-discovery-provider</artifactId>
<version>1.8.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.dspace</groupId>
<artifactId>dspace-discovery-solr</artifactId>
<version>1.8.0-SNAPSHOT</version>
</dependency>
<!-- DSpace third Party Dependencies -->
<!-- Explicitly Specify Latest Version of Spring -->