Merge pull request #67 from abollini/DS-1218

DS-1218 BrowseDAO based on discovery
This commit is contained in:
abollini
2012-09-08 07:08:46 -07:00
14 changed files with 2442 additions and 680 deletions

View File

@@ -29,19 +29,34 @@ public class BrowseDAOFactory
public static BrowseDAO getInstance(Context context)
throws BrowseException
{
String db = ConfigurationManager.getProperty("db.name");
if ("postgres".equals(db))
{
return new BrowseDAOPostgres(context);
}
else if ("oracle".equals(db))
{
return new BrowseDAOOracle(context);
}
else
{
throw new BrowseException("The configuration for db.name is either invalid, or contains an unrecognised database");
}
String className = ConfigurationManager.getProperty("browseDAO.class");
if (className == null)
{
// For compatibility with previous versions
String db = ConfigurationManager.getProperty("db.name");
if ("postgres".equals(db))
{
return new BrowseDAOPostgres(context);
}
else if ("oracle".equals(db))
{
return new BrowseDAOOracle(context);
}
else
{
throw new BrowseException("The configuration for db.name is either invalid, or contains an unrecognised database");
}
}
try
{
return (BrowseDAO) Class
.forName(ConfigurationManager.getProperty("browseDAO.class"))
.getConstructor(Context.class).newInstance(context);
}
catch (Exception e)
{
throw new BrowseException("The configuration for browseDAO is invalid: "+className, e);
}
}
/**
@@ -55,19 +70,34 @@ public class BrowseDAOFactory
public static BrowseCreateDAO getCreateInstance(Context context)
throws BrowseException
{
String db = ConfigurationManager.getProperty("db.name");
if ("postgres".equals(db))
{
return new BrowseCreateDAOPostgres(context);
}
else if ("oracle".equals(db))
{
return new BrowseCreateDAOOracle(context);
}
else
{
throw new BrowseException("The configuration for db.name is either invalid, or contains an unrecognised database");
}
String className = ConfigurationManager.getProperty("browseCreateDAO.class");
if (className == null)
{
// For compatibility with previous versions
String db = ConfigurationManager.getProperty("db.name");
if ("postgres".equals(db))
{
return new BrowseCreateDAOPostgres(context);
}
else if ("oracle".equals(db))
{
return new BrowseCreateDAOOracle(context);
}
else
{
throw new BrowseException("The configuration for db.name is either invalid, or contains an unrecognised database");
}
}
try
{
return (BrowseCreateDAO) Class
.forName(ConfigurationManager.getProperty("browseCreateDAO.class"))
.getConstructor(Context.class).newInstance(context);
}
catch (Exception e)
{
throw new BrowseException("The configuration for browseCreateDAO is invalid: "+className, e);
}
}
/**

View File

@@ -0,0 +1,89 @@
/**
* 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.content.authority;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
/**
* This is a *very* stupid test fixture for authority control with AuthorityVariantsSupport.
*
* @author Andrea Bollini (CILEA)
*/
public class TestAuthority implements ChoiceAuthority, AuthorityVariantsSupport
{
@Override
public List<String> getVariants(String key, String locale)
{
if (StringUtils.isNotBlank(key))
{
List<String> variants = new ArrayList<String>();
for (int i = 0; i < 3; i++)
{
variants.add(key+"_variant#"+i);
}
return variants;
}
return null;
}
@Override
public Choices getMatches(String field, String text, int collection,
int start, int limit, String locale)
{
Choices choices = new Choices(false);
if (StringUtils.isNotBlank(text))
{
List<Choice> choiceValues = new ArrayList<Choice>();
for (int i = 0; i < 3; i++)
{
choiceValues.add(new Choice(text + "_authority#" + i, text
+ "_value#" + i, text + "_label#" + i));
}
choices = new Choices(
(Choice[]) choiceValues.toArray(new Choice[choiceValues
.size()]), 0, 3, Choices.CF_AMBIGUOUS, false);
}
return choices;
}
@Override
public Choices getBestMatch(String field, String text, int collection,
String locale)
{
Choices choices = new Choices(false);
if (StringUtils.isNotBlank(text))
{
List<Choice> choiceValues = new ArrayList<Choice>();
choiceValues.add(new Choice(text + "_authoritybest", text
+ "_valuebest", text + "_labelbest"));
choices = new Choices(
(Choice[]) choiceValues.toArray(new Choice[choiceValues
.size()]), 0, 3, Choices.CF_UNCERTAIN, false);
}
return choices;
}
@Override
public String getLabel(String field, String key, String locale)
{
if (StringUtils.isNotBlank(key))
{
return key.replaceAll("authority", "label");
}
return "Unknown";
}
}

View File

@@ -110,11 +110,15 @@ public class DiscoverResult {
public static final class FacetResult{
private String asFilterQuery;
private String displayedValue;
private String authorityKey;
private String sortValue;
private long count;
public FacetResult(String asFilterQuery, String displayedValue, long count) {
public FacetResult(String asFilterQuery, String displayedValue, String authorityKey, String sortValue, long count) {
this.asFilterQuery = asFilterQuery;
this.displayedValue = displayedValue;
this.authorityKey = authorityKey;
this.sortValue = sortValue;
this.count = count;
}
@@ -126,9 +130,19 @@ public class DiscoverResult {
return displayedValue;
}
public String getSortValue()
{
return sortValue;
}
public long getCount() {
return count;
}
public String getAuthorityKey()
{
return authorityKey;
}
}
public static final class DSpaceObjectHighlightResult

View File

@@ -25,10 +25,76 @@ import java.util.List;
*/
public interface SearchService {
DiscoverResult search(Context context, DiscoverQuery query) throws SearchServiceException;
/**
* Convenient method to call @see #search(Context, DSpaceObject,
* DiscoverQuery) with a null DSpace Object as scope (i.e. all the
* repository)
*
* @param context
* DSpace Context object
* @param dso
* a DSpace Object to use as scope of the search (only results
* within this object)
* @param query
* the discovery query object
* @return
* @throws SearchServiceException
*/
DiscoverResult search(Context context, DiscoverQuery query)
throws SearchServiceException;
DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery query) throws SearchServiceException;
/**
* Convenient method to call @see #search(Context, DSpaceObject,
* DiscoverQuery, boolean) with includeWithdrawn=false
*
* @param context
* DSpace Context object
* @param dso
* a DSpace Object to use as scope of the search (only results
* within this object)
* @param query
* the discovery query object
* @return
* @throws SearchServiceException
*/
DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery query)
throws SearchServiceException;
/**
*
* @param context
* DSpace Context object
* @param dso
* a DSpace Object to use as scope of the search (only results
* within this object)
* @param includeWithdrawn
* use <code>true</code> to include in the results also withdrawn
* items that match the query
* @return
* @throws SearchServiceException
*/
DiscoverResult search(Context context, DiscoverQuery query,
boolean includeWithdrawn) throws SearchServiceException;
/**
*
* @param context
* DSpace Context object
* @param dso
* a DSpace Object to use as scope of the search (only results
* within this object)
* @param query
* the discovery query object
* @param includeWithdrawn
* use <code>true</code> to include in the results also withdrawn
* items that match the query
*
* @return
* @throws SearchServiceException
*/
DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery query, boolean includeWithdrawn) throws SearchServiceException;
InputStream searchJSON(Context context, DiscoverQuery query, String jsonIdentifier) throws SearchServiceException;
InputStream searchJSON(Context context, DiscoverQuery query, DSpaceObject dso, String jsonIdentifier) throws SearchServiceException;
@@ -36,6 +102,7 @@ public interface SearchService {
List<DSpaceObject> search(Context context, String query, String orderfield, boolean ascending, int offset, int max, String... filterquery);
/**
* Transforms the given string field and value into a filter query
* @param context the DSpace context
@@ -46,7 +113,7 @@ public interface SearchService {
*/
DiscoverFilterQuery toFilterQuery(Context context, String field, String operator, String value) throws SQLException;
List<Item> getRelatedItems(Context context, Item item, DiscoveryMoreLikeThisConfiguration moreLikeThisConfiguration);
List<Item> getRelatedItems(Context context, Item item, DiscoveryMoreLikeThisConfiguration moreLikeThisConfiguration);
/**
* Transforms the metadata field of the given sort configuration into the indexed field which we can then use in our solr queries

View File

@@ -0,0 +1,533 @@
/**
* 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.browse;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.solr.common.SolrInputDocument;
import org.dspace.content.DCValue;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.authority.ChoiceAuthorityManager;
import org.dspace.content.authority.MetadataAuthorityManager;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context;
import org.dspace.discovery.SolrServiceImpl;
import org.dspace.discovery.SolrServiceIndexPlugin;
import org.dspace.sort.OrderFormat;
import org.dspace.sort.SortException;
import org.dspace.sort.SortOption;
import org.dspace.utils.DSpace;
/**
*
* @author Andrea Bollini (CILEA)
*
*/
public class SolrBrowseCreateDAO implements BrowseCreateDAO,
SolrServiceIndexPlugin
{
private static final String INFO_NOSQL_TO_RUN = "No SQL to run: data are stored in the SOLR Search Core. PLEASE NOTE THAT YOU MUST UPDATE THE DISCOVERY INDEX AFTER ANY CHANGES TO THE BROWSE CONFIGURATION";
// reference to a DBMS BrowseCreateDAO needed to remove old tables when
// switching from DBMS to SOLR
private BrowseCreateDAO dbCreateDAO;
private static final Logger log = Logger
.getLogger(SolrBrowseCreateDAO.class);
private BrowseIndex[] bis;
public SolrBrowseCreateDAO()
{
try
{
bis = BrowseIndex.getBrowseIndices();
}
catch (BrowseException e)
{
log.error(e.getMessage(), e);
throw new IllegalStateException(e);
}
for (BrowseIndex bi : bis)
bi.generateMdBits();
}
public SolrBrowseCreateDAO(Context context) throws BrowseException
{
// For compatibility with previous versions
String db = ConfigurationManager.getProperty("db.name");
if ("postgres".equals(db))
{
dbCreateDAO = new BrowseCreateDAOPostgres(context);
}
else if ("oracle".equals(db))
{
dbCreateDAO = new BrowseCreateDAOOracle(context);
}
else
{
throw new BrowseException(
"The configuration for db.name is either invalid, or contains an unrecognised database");
}
try
{
bis = BrowseIndex.getBrowseIndices();
}
catch (BrowseException e)
{
log.error(e.getMessage(), e);
throw new IllegalStateException(e);
}
for (BrowseIndex bi : bis)
bi.generateMdBits();
}
@Override
public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument doc)
{
if (!(dso instanceof Item))
{
return;
}
Item item = (Item) dso;
// faceting for metadata browsing. It is different than search facet
// because if there are authority with variants support we wan't all the
// variants to go in the facet... they are sorted by count so just the
// prefered label is relevant
for (BrowseIndex bi : bis)
{
log.debug("Indexing for item " + item.getID() + ", for index: "
+ bi.getTableName());
if (bi.isMetadataIndex())
{
// values to show in the browse list
Set<String> distFValues = new HashSet<String>();
// value for lookup without authority
Set<String> distFVal = new HashSet<String>();
// value for lookup with authority
Set<String> distFAuths = new HashSet<String>();
// value for lookup when partial search (the item mapper tool use it)
Set<String> distValuesForAC = new HashSet<String>();
// now index the new details - but only if it's archived and not
// withdrawn
if (item.isArchived() || item.isWithdrawn())
{
// get the metadata from the item
for (int mdIdx = 0; mdIdx < bi.getMetadataCount(); mdIdx++)
{
String[] md = bi.getMdBits(mdIdx);
DCValue[] values = item.getMetadata(md[0], md[1],
md[2], Item.ANY);
// if we have values to index on, then do so
if (values != null && values.length > 0)
{
int minConfidence = MetadataAuthorityManager
.getManager().getMinConfidence(
values[0].schema,
values[0].element,
values[0].qualifier);
boolean ignoreAuthority = new DSpace()
.getConfigurationService()
.getPropertyAsType(
"discovery.browse.authority.ignore."
+ bi.getName(),
new DSpace()
.getConfigurationService()
.getPropertyAsType(
"discovery.browse.authority.ignore",
new Boolean(false)),
true);
for (int x = 0; x < values.length; x++)
{
// Ensure that there is a value to index before
// inserting it
if (StringUtils.isEmpty(values[x].value))
{
log.error("Null metadata value for item "
+ item.getID()
+ ", field: "
+ values[x].schema
+ "."
+ values[x].element
+ (values[x].qualifier == null ? ""
: "." + values[x].qualifier));
}
else
{
if (bi.isAuthorityIndex()
&& (values[x].authority == null || values[x].confidence < minConfidence))
{
// if we have an authority index only
// authored metadata will go here!
log.debug("Skipping item="
+ item.getID() + ", field="
+ values[x].schema + "."
+ values[x].element + "."
+ values[x].qualifier
+ ", value=" + values[x].value
+ ", authority="
+ values[x].authority
+ ", confidence="
+ values[x].confidence
+ " (BAD AUTHORITY)");
continue;
}
// is there any valid (with appropriate
// confidence) authority key?
if ((ignoreAuthority && !bi.isAuthorityIndex())
|| (values[x].authority != null && values[x].confidence >= minConfidence))
{
distFAuths.add(values[x].authority);
distValuesForAC.add(values[x].value);
String preferedLabel = null;
boolean ignorePrefered = new DSpace()
.getConfigurationService()
.getPropertyAsType(
"discovery.browse.authority.ignore-prefered."
+ bi.getName(),
new DSpace()
.getConfigurationService()
.getPropertyAsType(
"discovery.browse.authority.ignore-prefered",
new Boolean(
false)),
true);
if (!ignorePrefered)
{
preferedLabel = ChoiceAuthorityManager
.getManager()
.getLabel(
values[x].schema,
values[x].element,
values[x].qualifier,
values[x].authority,
values[x].language);
}
List<String> variants = null;
boolean ignoreVariants = new DSpace()
.getConfigurationService()
.getPropertyAsType(
"discovery.browse.authority.ignore-variants."
+ bi.getName(),
new DSpace()
.getConfigurationService()
.getPropertyAsType(
"discovery.browse.authority.ignore-variants",
new Boolean(
false)),
true);
if (!ignoreVariants)
{
variants = ChoiceAuthorityManager
.getManager()
.getVariants(
values[x].schema,
values[x].element,
values[x].qualifier,
values[x].authority,
values[x].language);
}
if (StringUtils
.isNotBlank(preferedLabel))
{
String nLabel = OrderFormat
.makeSortString(
preferedLabel,
values[x].language,
bi.getDataType());
distFValues
.add(nLabel
+ SolrServiceImpl.FILTER_SEPARATOR
+ preferedLabel
+ SolrServiceImpl.AUTHORITY_SEPARATOR
+ values[x].authority);
distValuesForAC.add(preferedLabel);
}
if (variants != null)
{
for (String var : variants)
{
String nVal = OrderFormat
.makeSortString(
var,
values[x].language,
bi.getDataType());
distFValues
.add(nVal
+ SolrServiceImpl.FILTER_SEPARATOR
+ var
+ SolrServiceImpl.AUTHORITY_SEPARATOR
+ values[x].authority);
distValuesForAC.add(var);
}
}
}
else
// put it in the browse index as if it
// hasn't have an authority key
{
// get the normalised version of the
// value
String nVal = OrderFormat
.makeSortString(
values[x].value,
values[x].language,
bi.getDataType());
distFValues
.add(nVal
+ SolrServiceImpl.FILTER_SEPARATOR
+ values[x].value);
distFVal.add(values[x].value);
distValuesForAC.add(values[x].value);
}
}
}
}
}
}
for (String facet : distFValues)
{
doc.addField(bi.getDistinctTableName() + "_filter", facet);
}
for (String facet : distFAuths)
{
doc.addField(bi.getDistinctTableName()
+ "_authority_filter", facet);
}
for (String facet : distValuesForAC)
{
doc.addField(bi.getDistinctTableName() + "_partial", facet);
}
for (String facet : distFVal)
{
doc.addField(bi.getDistinctTableName()+"_value_filter", facet);
}
}
}
// Add sorting options as configurated for the browse system
try
{
for (SortOption so : SortOption.getSortOptions())
{
DCValue[] dcvalue = item.getMetadata(so.getMetadata());
if (dcvalue != null && dcvalue.length > 0)
{
String nValue = OrderFormat
.makeSortString(dcvalue[0].value,
dcvalue[0].language, so.getType());
doc.addField("bi_sort_" + so.getNumber() + "_sort", nValue);
}
}
}
catch (SortException e)
{
// we can't solve it so rethrow as runtime exception
throw new RuntimeException(e.getMessage(), e);
}
}
@Override
public void deleteByItemID(String table, int itemID) throws BrowseException
{
}
@Override
public void deleteCommunityMappings(int itemID) throws BrowseException
{
}
@Override
public void updateCommunityMappings(int itemID) throws BrowseException
{
}
@Override
public void insertIndex(String table, int itemID, Map sortCols)
throws BrowseException
{
}
@Override
public boolean updateIndex(String table, int itemID, Map sortCols)
throws BrowseException
{
return false;
}
@Override
public int getDistinctID(String table, String value, String authority,
String sortValue) throws BrowseException
{
// TODO Auto-generated method stub
return 0;
}
@Override
public int insertDistinctRecord(String table, String value,
String authority, String sortValue) throws BrowseException
{
// TODO Auto-generated method stub
return 0;
}
@Override
public String dropIndexAndRelated(String table, boolean execute)
throws BrowseException
{
return dbCreateDAO.dropIndexAndRelated(table, execute);
}
@Override
public String dropSequence(String sequence, boolean execute)
throws BrowseException
{
return dbCreateDAO.dropSequence(sequence, execute);
}
@Override
public String dropView(String view, boolean execute) throws BrowseException
{
return dbCreateDAO.dropView(view, execute);
}
@Override
public String createSequence(String sequence, boolean execute)
throws BrowseException
{
return INFO_NOSQL_TO_RUN;
}
@Override
public String createPrimaryTable(String table, List sortCols,
boolean execute) throws BrowseException
{
return INFO_NOSQL_TO_RUN;
}
@Override
public String[] createDatabaseIndices(String table, List<Integer> sortCols,
boolean value, boolean execute) throws BrowseException
{
return new String[] { INFO_NOSQL_TO_RUN };
}
@Override
public String[] createMapIndices(String disTable, String mapTable,
boolean execute) throws BrowseException
{
return new String[] { INFO_NOSQL_TO_RUN };
}
@Override
public String createCollectionView(String table, String view,
boolean execute) throws BrowseException
{
return INFO_NOSQL_TO_RUN;
}
@Override
public String createCommunityView(String table, String view, boolean execute)
throws BrowseException
{
return INFO_NOSQL_TO_RUN;
}
@Override
public String createDistinctTable(String table, boolean execute)
throws BrowseException
{
return INFO_NOSQL_TO_RUN;
}
@Override
public String createDistinctMap(String table, String map, boolean execute)
throws BrowseException
{
return INFO_NOSQL_TO_RUN;
}
public MappingResults updateDistinctMappings(String table, int itemID,
Set<Integer> distinctIDs) throws BrowseException
{
return new MappingResults()
{
@Override
public List<Integer> getRetainedDistinctIds()
{
return new ArrayList<Integer>();
}
@Override
public List<Integer> getRemovedDistinctIds()
{
return new ArrayList<Integer>();
}
@Override
public List<Integer> getAddedDistinctIds()
{
return new ArrayList<Integer>();
}
};
}
@Override
public boolean testTableExistence(String table) throws BrowseException
{
return dbCreateDAO.testTableExistence(table);
}
@Override
public List<Integer> deleteMappingsByItemID(String mapTable, int itemID)
throws BrowseException
{
return new ArrayList<Integer>();
}
@Override
public void pruneExcess(String table, boolean withdrawn)
throws BrowseException
{
}
@Override
public void pruneMapExcess(String map, boolean withdrawn,
List<Integer> distinctIds) throws BrowseException
{
}
@Override
public void pruneDistinct(String table, String map,
List<Integer> distinctIds) throws BrowseException
{
}
}

View File

@@ -0,0 +1,741 @@
/**
* 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.browse;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.apache.log4j.Logger;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.discovery.DiscoverFacetField;
import org.dspace.discovery.DiscoverQuery;
import org.dspace.discovery.DiscoverQuery.SORT_ORDER;
import org.dspace.discovery.DiscoverResult;
import org.dspace.discovery.DiscoverResult.FacetResult;
import org.dspace.discovery.DiscoverResult.SearchDocument;
import org.dspace.discovery.SearchService;
import org.dspace.discovery.SearchServiceException;
import org.dspace.discovery.configuration.DiscoveryConfigurationParameters;
import org.dspace.utils.DSpace;
/**
*
* @author Andrea Bollini (CILEA)
*
*/
public class SolrBrowseDAO implements BrowseDAO
{
public SolrBrowseDAO(Context context)
{
this.context = context;
}
static private class FacetValueComparator implements Comparator
{
@Override
public int compare(Object o1, Object o2)
{
String s1 = "", s2 = "";
if (o1 instanceof FacetResult && o2 instanceof String)
{
FacetResult c = (FacetResult) o1;
s1 = c.getSortValue();
s2 = (String) o2;
}
else if (o2 instanceof FacetResult && o1 instanceof String)
{
FacetResult c = (FacetResult) o2;
s1 = (String) o1;
s2 = c.getSortValue();
}
// both object are FacetResult so they are already sorted
return s1.compareTo(s2);
}
}
/** Log4j log */
private static Logger log = Logger.getLogger(SolrBrowseDAO.class);
/** The DSpace context */
private Context context;
// SQL query related attributes for this class
/** table(s) to select from */
private String table = null;
/** field to look for focus value in */
private String focusField = null;
/** value to start browse from in focus field */
private String focusValue = null;
/** field to look for value in */
private String valueField = null;
/** value to restrict browse to (e.g. author name) */
private String value = null;
private String authority = null;
/** exact or partial matching of the value */
private boolean valuePartial = false;
/** the table that defines the mapping for the relevant container */
private String containerTable = null;
/**
* the name of the field which contains the container id (e.g.
* collection_id)
*/
private String containerIDField = null;
/** the database id of the container we are constraining to */
private int containerID = -1;
/** the column that we are sorting results by */
private String orderField = null;
/** whether to sort results ascending or descending */
private boolean ascending = true;
/** the limit of number of results to return */
private int limit = -1;
/** the offset of the start point */
private int offset = 0;
/** whether to use the equals comparator in value comparisons */
private boolean equalsComparator = true;
/** whether this is a distinct browse or not */
private boolean distinct = false;
private String facetField;
// administrative attributes for this class
DSpace dspace = new DSpace();
SearchService searcher = dspace.getServiceManager().getServiceByName(
SearchService.class.getName(), SearchService.class);
private DiscoverResult sResponse = null;
private boolean itemsWithdrawn = false;
private boolean itemsPrivate = false;
private DiscoverResult getSolrResponse() throws BrowseException
{
if (sResponse == null)
{
DiscoverQuery query = new DiscoverQuery();
addLocationScopeFilter(query);
addStatusFilter(query);
if (distinct)
{
DiscoverFacetField dff = new DiscoverFacetField(facetField,
DiscoveryConfigurationParameters.TYPE_TEXT, -1,
DiscoveryConfigurationParameters.SORT.VALUE);
query.addFacetField(dff);
query.setFacetMinCount(1);
query.setMaxResults(0);
}
else
{
query.setMaxResults(limit > 0 ? limit : 20);
if (offset > 0)
{
query.setStart(offset);
}
// caution check first authority, value is always present!
if (authority != null)
{
query.addFilterQueries("{!field f="+facetField + "_authority_filter}"
+ authority);
}
else if (value != null && !valuePartial)
{
query.addFilterQueries("{!field f="+facetField + "_value_filter}" + value);
}
else if (valuePartial)
{
query.addFilterQueries("{!field f="+facetField + "_partial}" + value);
}
// filter on item to be sure to don't include any other object
// indexed in the Discovery Search core
query.addFilterQueries("search.resourcetype:" + Constants.ITEM);
if (orderField != null)
{
query.setSortField("bi_" + orderField + "_sort",
ascending ? SORT_ORDER.asc : SORT_ORDER.desc);
}
}
try
{
sResponse = searcher.search(context, query, itemsWithdrawn);
}
catch (SearchServiceException e)
{
throw new BrowseException(e);
}
}
return sResponse;
}
private void addStatusFilter(DiscoverQuery query)
{
if (itemsWithdrawn)
{
query.addFilterQueries("withdrawn:true");
if (itemsPrivate)
{
query.addFilterQueries("discoverable:false");
}
else
{
query.addFilterQueries("NOT(discoverable:false)");
}
}
else
{
query.addFilterQueries("NOT(withdrawn:true)");
}
}
private void addLocationScopeFilter(DiscoverQuery query)
{
if (containerID > 0)
{
if (containerIDField.startsWith("collection"))
{
query.addFilterQueries("location.coll:" + containerID);
}
else if (containerIDField.startsWith("community"))
{
query.addFilterQueries("location.comm:" + containerID);
}
}
}
@Override
public int doCountQuery() throws BrowseException
{
DiscoverResult resp = getSolrResponse();
int count = 0;
if (distinct)
{
List<FacetResult> facetResults = resp.getFacetResult(facetField);
count = facetResults.size();
}
else
{
// we need to cast to int to respect the BrowseDAO contract...
count = (int) resp.getTotalSearchResults();
// FIXME null the response cache
// the BrowseEngine send fake argument to the BrowseDAO for the
// count...
sResponse = null;
}
return count;
}
@Override
public List doValueQuery() throws BrowseException
{
DiscoverResult resp = getSolrResponse();
List<FacetResult> facet = resp.getFacetResult(facetField);
int count = doCountQuery();
int start = offset > 0 ? offset : 0;
int max = limit > 0 ? limit : 20;
List<String[]> result = new ArrayList<String[]>();
if (ascending)
{
for (int i = start; i < (start + max) && i < count; i++)
{
FacetResult c = facet.get(i);
result.add(new String[] { c.getDisplayedValue(),
c.getAuthorityKey() });
}
}
else
{
for (int i = count - start - 1; i >= count - (start + max)
&& i >= 0; i--)
{
FacetResult c = facet.get(i);
result.add(new String[] { c.getDisplayedValue(),
c.getAuthorityKey() });
}
}
return result;
}
@Override
public List doQuery() throws BrowseException
{
DiscoverResult resp = getSolrResponse();
List<BrowseItem> bitems = new ArrayList<BrowseItem>();
for (DSpaceObject solrDoc : resp.getDspaceObjects())
{
// FIXME introduce project, don't retrieve Item immediately when
// processing the query...
Item item = (Item) solrDoc;
BrowseItem bitem = new BrowseItem(context, item.getID(),
item.isArchived(), item.isWithdrawn());
bitems.add(bitem);
}
return bitems;
}
@Override
public String doMaxQuery(String column, String table, int itemID)
throws BrowseException
{
DiscoverQuery query = new DiscoverQuery();
query.setQuery("search.resourceid:" + itemID
+ " AND search.resourcetype:" + Constants.ITEM);
query.setMaxResults(1);
DiscoverResult resp = null;
try
{
resp = searcher.search(context, query);
}
catch (SearchServiceException e)
{
throw new BrowseException(e);
}
if (resp.getTotalSearchResults() > 0)
{
SearchDocument doc = resp.getSearchDocument(
resp.getDspaceObjects().get(0)).get(0);
return (String) doc.getSearchFieldValues(column).get(0);
}
return null;
}
@Override
public int doOffsetQuery(String column, String value, boolean isAscending)
throws BrowseException
{
DiscoverQuery query = new DiscoverQuery();
addLocationScopeFilter(query);
addStatusFilter(query);
query.setMaxResults(0);
query.addFilterQueries("search.resourcetype:" + Constants.ITEM);
if (isAscending)
{
query.setQuery("bi_"+column + "_sort" + ": [* TO \"" + value + "\"]");
}
else
{
query.setQuery("bi_" + column + "_sort" + ": [\"" + value + "\" TO *]");
}
DiscoverResult resp = null;
try
{
resp = searcher.search(context, query);
}
catch (SearchServiceException e)
{
throw new BrowseException(e);
}
return (int) resp.getTotalSearchResults();
}
@Override
public int doDistinctOffsetQuery(String column, String value,
boolean isAscending) throws BrowseException
{
DiscoverResult resp = getSolrResponse();
List<FacetResult> facets = resp.getFacetResult(facetField);
Comparator comparator = new SolrBrowseDAO.FacetValueComparator();
Collections.sort(facets, comparator);
int x = Collections.binarySearch(facets, value, comparator);
int ascValue = (x >= 0) ? x : -(x + 1);
if (isAscending)
{
return ascValue;
}
else
{
return doCountQuery() - ascValue;
}
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#getContainerID()
*/
public int getContainerID()
{
return containerID;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#getContainerIDField()
*/
public String getContainerIDField()
{
return containerIDField;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#getContainerTable()
*/
public String getContainerTable()
{
return containerTable;
}
// FIXME is this in use?
public String[] getCountValues()
{
return null;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#getFocusField()
*/
public String getJumpToField()
{
return focusField;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#getFocusValue()
*/
public String getJumpToValue()
{
return focusValue;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#getLimit()
*/
public int getLimit()
{
return limit;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#getOffset()
*/
public int getOffset()
{
return offset;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#getOrderField()
*/
public String getOrderField()
{
return orderField;
}
// is this in use?
public String[] getSelectValues()
{
return null;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#getTable()
*/
public String getTable()
{
return table;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#getValue()
*/
public String getFilterValue()
{
return value;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#getValueField()
*/
public String getFilterValueField()
{
return valueField;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#isAscending()
*/
public boolean isAscending()
{
return ascending;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#isDistinct()
*/
public boolean isDistinct()
{
return this.distinct;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#setAscending(boolean)
*/
public void setAscending(boolean ascending)
{
this.ascending = ascending;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#setContainerID(int)
*/
public void setContainerID(int containerID)
{
this.containerID = containerID;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#setContainerIDField(java.lang.String)
*/
public void setContainerIDField(String containerIDField)
{
this.containerIDField = containerIDField;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#setContainerTable(java.lang.String)
*/
public void setContainerTable(String containerTable)
{
this.containerTable = containerTable;
}
// is this in use?
public void setCountValues(String[] fields)
{
// this.countValues = fields;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#setDistinct(boolean)
*/
public void setDistinct(boolean bool)
{
this.distinct = bool;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#setEqualsComparator(boolean)
*/
public void setEqualsComparator(boolean equalsComparator)
{
this.equalsComparator = equalsComparator;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#setFocusField(java.lang.String)
*/
public void setJumpToField(String focusField)
{
this.focusField = focusField;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#setFocusValue(java.lang.String)
*/
public void setJumpToValue(String focusValue)
{
this.focusValue = focusValue;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#setLimit(int)
*/
public void setLimit(int limit)
{
this.limit = limit;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#setOffset(int)
*/
public void setOffset(int offset)
{
this.offset = offset;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#setOrderField(java.lang.String)
*/
public void setOrderField(String orderField)
{
this.orderField = orderField;
}
// is this in use?
public void setSelectValues(String[] selectValues)
{
// this.selectValues = selectValues;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#setTable(java.lang.String)
*/
public void setTable(String table)
{
if (table.equals(BrowseIndex.getWithdrawnBrowseIndex().getTableName()))
{
itemsWithdrawn = true;
itemsPrivate = false;
}
else if (table.equals(BrowseIndex.getPrivateBrowseIndex().getTableName()))
{
itemsPrivate = true;
// items private are also withdrawn
itemsWithdrawn = true;
}
facetField = table;
}
public void setFilterMappingTables(String tableDis, String tableMap)
{
if (tableDis != null)
{
this.facetField = tableDis;
}
// this.fields = tableDis;
// this.tableMap = tableMap;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#setValue(java.lang.String)
*/
public void setFilterValue(String value)
{
this.value = value;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#setFilterValuePartial(boolean)
*/
public void setFilterValuePartial(boolean part)
{
this.valuePartial = part;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#setValueField(java.lang.String)
*/
public void setFilterValueField(String valueField)
{
this.valueField = valueField;
}
/*
* (non-Javadoc)
*
* @see org.dspace.browse.BrowseDAO#useEqualsComparator()
*/
public boolean useEqualsComparator()
{
return equalsComparator;
}
@Override
public String getAuthorityValue()
{
return authority;
}
@Override
public void setAuthorityValue(String value)
{
this.authority = value;
}
}

View File

@@ -33,6 +33,9 @@ import org.apache.solr.common.params.MoreLikeThisParams;
import org.apache.solr.common.util.NamedList;
import org.dspace.content.*;
import org.dspace.content.Collection;
import org.dspace.content.authority.ChoiceAuthorityManager;
import org.dspace.content.authority.Choices;
import org.dspace.content.authority.MetadataAuthorityManager;
import org.dspace.core.*;
import org.dspace.discovery.configuration.*;
import org.dspace.handle.HandleManager;
@@ -74,6 +77,12 @@ public class SolrServiceImpl implements SearchService, IndexingService {
public static final String FILTER_SEPARATOR = "\n|||\n";
public static final String AUTHORITY_SEPARATOR = "\n§§§\n";
public static final String STORE_SEPARATOR = "\n|||\n";
public static final String VARIANTS_STORE_SEPARATOR = "\n§§§\n";
/**
* Non-Static CommonsHttpSolrServer for processing indexing events.
*/
@@ -141,7 +150,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
{
case Constants.ITEM:
Item item = (Item) dso;
if (item.isArchived() && !item.isWithdrawn())
if (item.isArchived() || item.isWithdrawn())
{
/**
* If the item is in the repository now, add it to the index
@@ -155,9 +164,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
} else {
/**
* Make sure the item is not in the index if it is not in
* archive. TODO: Someday DSIndexer should block withdrawn
* content on search/retrieval and allow admins the ability
* to still search for withdrawn Items.
* archive or withwrawn.
*/
unIndexContent(context, handle);
log.info("Removed Item: " + handle + " from Index");
@@ -721,9 +728,12 @@ public class SolrServiceImpl implements SearchService, IndexingService {
SolrInputDocument doc = buildDocument(Constants.ITEM, item.getID(), handle,
locations);
log.debug("Building Item: " + handle);
doc.addField("withdrawn", item.isWithdrawn());
doc.addField("discoverable", item.isDiscoverable());
//Keep a list of our sort values which we added, sort values can only be added once
List<String> sortFieldsAdded = new ArrayList<String>();
Set<String> hitHighlightingFields = new HashSet<String>();
@@ -780,7 +790,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
{
hitHighlightingFields.add(fieldConfiguration.getField());
}
}
}
DiscoveryMoreLikeThisConfiguration moreLikeThisConfiguration = discoveryConfiguration.getMoreLikeThisConfiguration();
if(moreLikeThisConfiguration != null)
{
@@ -805,6 +815,19 @@ public class SolrServiceImpl implements SearchService, IndexingService {
toIgnoreFields.add(ignoreFieldsString);
}
}
List<String> toProjectionFields = new ArrayList<String>();
String projectionFieldsString = new DSpace().getConfigurationService().getProperty("discovery.index.projection");
if(projectionFieldsString != null){
if(projectionFieldsString.indexOf(",") != -1){
for (int i = 0; i < projectionFieldsString.split(",").length; i++) {
toProjectionFields.add(projectionFieldsString.split(",")[i].trim());
}
} else {
toProjectionFields.add(projectionFieldsString);
}
}
DCValue[] mydc = item.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY);
for (DCValue meta : mydc)
{
@@ -813,7 +836,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
String value = meta.value;
if (value == null)
if (value == null)
{
continue;
}
@@ -823,12 +846,83 @@ public class SolrServiceImpl implements SearchService, IndexingService {
field += "." + meta.qualifier;
}
//We are not indexing provenance, this is useless
if (toIgnoreFields.contains(field) || toIgnoreFields.contains(unqualifiedField + "." + Item.ANY))
{
continue;
}
String authority = null;
String preferedLabel = null;
List<String> variants = null;
boolean isAuthorityControlled = MetadataAuthorityManager
.getManager().isAuthorityControlled(meta.schema,
meta.element,
meta.qualifier);
int minConfidence = isAuthorityControlled?MetadataAuthorityManager
.getManager().getMinConfidence(
meta.schema,
meta.element,
meta.qualifier):Choices.CF_ACCEPTED;
if (isAuthorityControlled && meta.authority != null
&& meta.confidence >= minConfidence)
{
boolean ignoreAuthority = new DSpace()
.getConfigurationService()
.getPropertyAsType(
"discovery.index.authority.ignore." + field,
new DSpace()
.getConfigurationService()
.getPropertyAsType(
"discovery.index.authority.ignore",
new Boolean(false)), true);
if (!ignoreAuthority)
{
authority = meta.authority;
boolean ignorePrefered = new DSpace()
.getConfigurationService()
.getPropertyAsType(
"discovery.index.authority.ignore-prefered."
+ field,
new DSpace()
.getConfigurationService()
.getPropertyAsType(
"discovery.index.authority.ignore-prefered",
new Boolean(false)),
true);
if (!ignorePrefered)
{
preferedLabel = ChoiceAuthorityManager.getManager()
.getLabel(meta.schema, meta.element,
meta.qualifier, meta.authority,
meta.language);
}
boolean ignoreVariants = new DSpace()
.getConfigurationService()
.getPropertyAsType(
"discovery.index.authority.ignore-variants."
+ field,
new DSpace()
.getConfigurationService()
.getPropertyAsType(
"discovery.index.authority.ignore-variants",
new Boolean(false)),
true);
if (!ignoreVariants)
{
variants = ChoiceAuthorityManager.getManager()
.getVariants(meta.schema, meta.element,
meta.qualifier, meta.authority,
meta.language);
}
}
}
if ((searchFilters.get(field) != null || searchFilters.get(unqualifiedField + "." + Item.ANY) != null))
{
@@ -851,37 +945,70 @@ public class SolrServiceImpl implements SearchService, IndexingService {
value = DateFormatUtils.formatUTC(date, "yyyy-MM-dd");
}
}
doc.addField(searchFilter.getIndexFieldName(), value);
doc.addField(searchFilter.getIndexFieldName() + "_keyword", value);
if (preferedLabel != null)
{
doc.addField(searchFilter.getIndexFieldName(), preferedLabel);
}
if (variants != null)
{
for (String var : variants)
{
doc.addField(searchFilter.getIndexFieldName(), var);
}
}
//Add a dynamic fields for auto complete in search
doc.addField(searchFilter.getIndexFieldName() + "_keyword", value);
if (preferedLabel != null)
{
doc.addField(searchFilter.getIndexFieldName() + "_keyword", preferedLabel);
}
if (variants != null)
{
for (String var : variants)
{
doc.addField(searchFilter.getIndexFieldName() + "_ac", var);
}
}
if(searchFilter.getFilterType().equals(DiscoverySearchFilterFacet.FILTER_TYPE_FACET))
{
if(searchFilter.getType().equals(DiscoveryConfigurationParameters.TYPE_TEXT))
{
//Add a special filter
//We use a separator to split up the lowercase and regular case, this is needed to get our filters in regular case
//Solr has issues with facet prefix and cases
String separator = new DSpace().getConfigurationService().getProperty("discovery.solr.facets.split.char");
//Add a special filter
//We use a separator to split up the lowercase and regular case, this is needed to get our filters in regular case
//Solr has issues with facet prefix and cases
String separator = new DSpace().getConfigurationService().getProperty("discovery.solr.facets.split.char");
if(separator == null)
{
separator = FILTER_SEPARATOR;
}
doc.addField(searchFilter.getIndexFieldName() + "_filter", value.toLowerCase() + separator + value);
separator = FILTER_SEPARATOR;
}
if (authority != null)
{
String facetValue = preferedLabel != null?preferedLabel:value;
doc.addField(searchFilter.getIndexFieldName() + "_filter", facetValue.toLowerCase() + separator + facetValue + AUTHORITY_SEPARATOR + authority);
}
else
{
doc.addField(searchFilter.getIndexFieldName() + "_filter", value.toLowerCase() + separator + value);
}
}else
if(searchFilter.getType().equals(DiscoveryConfigurationParameters.TYPE_DATE))
{
if(date != null)
if(searchFilter.getType().equals(DiscoveryConfigurationParameters.TYPE_DATE))
{
String indexField = searchFilter.getIndexFieldName() + ".year";
doc.addField(searchFilter.getIndexFieldName() + "_keyword", DateFormatUtils.formatUTC(date, "yyyy"));
doc.addField(indexField, DateFormatUtils.formatUTC(date, "yyyy"));
//Also save a sort value of this year, this is required for determining the upper & lower bound year of our facet
if(doc.getField(indexField + "_sort") == null)
if(date != null)
{
//We can only add one year so take the first one
doc.addField(indexField + "_sort", DateFormatUtils.formatUTC(date, "yyyy"));
}
String indexField = searchFilter.getIndexFieldName() + ".year";
doc.addField(searchFilter.getIndexFieldName() + "_keyword", DateFormatUtils.formatUTC(date, "yyyy"));
doc.addField(indexField, DateFormatUtils.formatUTC(date, "yyyy"));
//Also save a sort value of this year, this is required for determining the upper & lower bound year of our facet
if(doc.getField(indexField + "_sort") == null)
{
//We can only add one year so take the first one
doc.addField(indexField + "_sort", DateFormatUtils.formatUTC(date, "yyyy"));
}
}
}else
if(searchFilter.getType().equals(DiscoveryConfigurationParameters.TYPE_HIERARCHICAL))
@@ -961,8 +1088,30 @@ public class SolrServiceImpl implements SearchService, IndexingService {
doc.addField(field + "_mlt", value);
}
doc.addField(field, value.toLowerCase());
doc.addField(field, value);
if (toProjectionFields.contains(field) || toProjectionFields.contains(unqualifiedField + "." + Item.ANY))
{
StringBuffer variantsToStore = new StringBuffer();
if (variants != null)
{
for (String var : variants)
{
variantsToStore.append(VARIANTS_STORE_SEPARATOR);
variantsToStore.append(var);
}
}
doc.addField(
field + "_stored",
value + STORE_SEPARATOR + preferedLabel
+ STORE_SEPARATOR
+ (variantsToStore.length() > VARIANTS_STORE_SEPARATOR
.length() ? variantsToStore
.substring(VARIANTS_STORE_SEPARATOR
.length()) : "null")
+ STORE_SEPARATOR + authority
+ STORE_SEPARATOR + meta.language);
}
if (meta.language != null && !meta.language.trim().equals(""))
{
String langField = field + "." + meta.language;
@@ -1212,7 +1361,21 @@ public class SolrServiceImpl implements SearchService, IndexingService {
}
//******** SearchService implementation
public DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery discoveryQuery) throws SearchServiceException {
@Override
public DiscoverResult search(Context context, DiscoverQuery query) throws SearchServiceException
{
return search(context, query, false);
}
@Override
public DiscoverResult search(Context context, DSpaceObject dso,
DiscoverQuery query)
throws SearchServiceException
{
return search(context, dso, query);
}
public DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery discoveryQuery, boolean includeWithdrawn) throws SearchServiceException {
if(dso != null)
{
if (dso instanceof Community)
@@ -1226,14 +1389,14 @@ public class SolrServiceImpl implements SearchService, IndexingService {
discoveryQuery.addFilterQueries("handle:" + dso.getHandle());
}
}
return search(context, discoveryQuery);
return search(context, discoveryQuery, includeWithdrawn);
}
public DiscoverResult search(Context context, DiscoverQuery discoveryQuery) throws SearchServiceException {
public DiscoverResult search(Context context, DiscoverQuery discoveryQuery, boolean includeWithdrawn) throws SearchServiceException {
try {
SolrQuery solrQuery = resolveToSolrQuery(context, discoveryQuery);
SolrQuery solrQuery = resolveToSolrQuery(context, discoveryQuery, includeWithdrawn);
QueryResponse queryResponse = getSolr().query(solrQuery);
@@ -1245,17 +1408,22 @@ public class SolrServiceImpl implements SearchService, IndexingService {
}
}
protected SolrQuery resolveToSolrQuery(Context context, DiscoverQuery discoveryQuery)
protected SolrQuery resolveToSolrQuery(Context context, DiscoverQuery discoveryQuery, boolean includeWithdrawn)
{
SolrQuery solrQuery = new SolrQuery();
String query = "*:*";
if(discoveryQuery.getQuery() != null)
{
query = discoveryQuery.getQuery();
}
query = discoveryQuery.getQuery();
}
solrQuery.setQuery(query);
if (!includeWithdrawn)
{
solrQuery.addFilterQuery("NOT(withdrawn:true)");
}
for (int i = 0; i < discoveryQuery.getFilterQueries().size(); i++)
{
@@ -1380,7 +1548,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
public InputStream searchJSON(Context context, DiscoverQuery discoveryQuery, String jsonIdentifier) throws SearchServiceException {
SolrQuery solrQuery = resolveToSolrQuery(context, discoveryQuery);
SolrQuery solrQuery = resolveToSolrQuery(context, discoveryQuery, false);
//We use json as out output type
solrQuery.setParam("json.nl", "map");
solrQuery.setParam("json.wrf", jsonIdentifier);
@@ -1401,7 +1569,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
}
return null;
}
protected DiscoverResult retrieveResult(Context context, DiscoverQuery query, QueryResponse solrQueryResponse) throws SQLException {
DiscoverResult result = new DiscoverResult();
@@ -1476,8 +1644,14 @@ public class SolrServiceImpl implements SearchService, IndexingService {
{
String displayedValue = transformDisplayedValue(context, facetField.getName(), facetValue.getName());
String field = transformFacetField(facetFieldConfig, facetField.getName(), true);
result.addFacetResult(field, new DiscoverResult.FacetResult(displayedValue, displayedValue, facetValue.getCount()));
String authorityValue = transformAuthorityValue(context, facetField.getName(), facetValue.getName());
String sortValue = transformSortValue(context, facetField.getName(), facetValue.getName());
result.addFacetResult(
field,
new DiscoverResult.FacetResult(facetValue
.getAsFilterQuery(),
displayedValue, authorityValue,
sortValue, facetValue.getCount()));
}
}
}
@@ -1498,13 +1672,13 @@ public class SolrServiceImpl implements SearchService, IndexingService {
name = name.substring(0, name.lastIndexOf(']')).replaceAll("TO", "-");
String filter = facetQuery.substring(facetQuery.indexOf('['));
filter = filter.substring(0, filter.lastIndexOf(']') + 1);
Integer count = sortedFacetQueries.get(facetQuery);
//No need to show empty years
if(0 < count)
{
result.addFacetResult(facetField, new DiscoverResult.FacetResult(filter, name, count));
result.addFacetResult(facetField, new DiscoverResult.FacetResult(filter, name, null, name, count));
}
}
}
@@ -1597,7 +1771,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
return new ArrayList<DSpaceObject>(0);
}
}
public DiscoverFilterQuery toFilterQuery(Context context, String field, String operator, String value) throws SQLException{
DiscoverFilterQuery result = new DiscoverFilterQuery();
@@ -1689,7 +1863,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
}
return results;
}
@Override
public String toSortFieldIndex(String metadataField, String type)
{
@@ -1761,6 +1935,68 @@ public class SolrServiceImpl implements SearchService, IndexingService {
StringBuffer valueBuffer = new StringBuffer();
int start = fqParts.length / 2;
for(int i = start; i < fqParts.length; i++)
{
String[] split = fqParts[i].split(AUTHORITY_SEPARATOR, 2);
valueBuffer.append(split[0]);
}
value = valueBuffer.toString();
}else if(value.matches("\\((.*?)\\)"))
{
//The brackets where added for better solr results, remove the first & last one
value = value.substring(1, value.length() -1);
}
return value;
}
protected String transformAuthorityValue(Context context, String field, String value) throws SQLException {
if(field.endsWith("_filter"))
{
//We have a filter make sure we split !
String separator = new DSpace().getConfigurationService().getProperty("discovery.solr.facets.split.char");
if(separator == null)
{
separator = FILTER_SEPARATOR;
}
//Escape any regex chars
separator = java.util.regex.Pattern.quote(separator);
String[] fqParts = value.split(separator);
StringBuffer authorityBuffer = new StringBuffer();
int start = fqParts.length / 2;
for(int i = start; i < fqParts.length; i++)
{
String[] split = fqParts[i].split(AUTHORITY_SEPARATOR, 2);
if (split.length == 2)
{
authorityBuffer.append(split[1]);
}
}
if (authorityBuffer.length() > 0)
{
return authorityBuffer.toString();
}
}
return null;
}
protected String transformSortValue(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 = new DSpace().getConfigurationService().getProperty("discovery.solr.facets.split.char");
if(separator == null)
{
separator = FILTER_SEPARATOR;
}
//Escape any regex chars
separator = java.util.regex.Pattern.quote(separator);
String[] fqParts = value.split(separator);
StringBuffer valueBuffer = new StringBuffer();
int end = fqParts.length / 2;
for(int i = 0; i < end; i++)
{
valueBuffer.append(fqParts[i]);
}

View File

@@ -623,7 +623,8 @@ public class PrivateItems extends AbstractDSpaceTransformer implements
params.scope.setJumpToItem(RequestUtils.getIntParameter(request, BrowseParams.JUMPTO_ITEM));
params.scope.setOrder(request.getParameter(BrowseParams.ORDER));
params.scope.setOffset(RequestUtils.getIntParameter(request, BrowseParams.OFFSET));
int offset = RequestUtils.getIntParameter(request, BrowseParams.OFFSET);
params.scope.setOffset(offset > 0 ? offset : 0);
params.scope.setResultsPerPage(RequestUtils.getIntParameter(request,
BrowseParams.RESULTS_PER_PAGE));
params.scope.setStartsWith(request.getParameter(BrowseParams.STARTS_WITH));

View File

@@ -623,7 +623,8 @@ public class WithdrawnItems extends AbstractDSpaceTransformer implements
params.scope.setJumpToItem(RequestUtils.getIntParameter(request, BrowseParams.JUMPTO_ITEM));
params.scope.setOrder(request.getParameter(BrowseParams.ORDER));
params.scope.setOffset(RequestUtils.getIntParameter(request, BrowseParams.OFFSET));
int offset = RequestUtils.getIntParameter(request, BrowseParams.OFFSET);
params.scope.setOffset(offset > 0 ? offset : 0);
params.scope.setResultsPerPage(RequestUtils.getIntParameter(request,
BrowseParams.RESULTS_PER_PAGE));
params.scope.setStartsWith(request.getParameter(BrowseParams.STARTS_WITH));

View File

@@ -853,6 +853,25 @@ webui.strengths.cache = false
###### Browse Configuration ######
#
# Define the DAO class to use this must meet your storage choice for
# the browse system (RDBMS: PostgreSQL or Oracle, SOLR).
# By default the standard RDBMS implementation for your db is used
#
# PostgreSQL:
# browseDAO.class = org.dspace.browse.BrowseDAOPostgres
# browseCreateDAO.class = org.dspace.browse.BrowseCreateDAOPostgres
#
# Oracle:
# browseDAO.class = org.dspace.browse.BrowseDAOOracle
# browseCreateDAO.class = org.dspace.browse.BrowseCreateDAOOracle
#
# SOLR:
# browseDAO.class = org.dspace.browse.SolrBrowseDAO
# browseCreateDAO.class = org.dspace.browse.SolrBrowseCreateDAO
#
# Use this to configure the browse indices. Each entry will receive a link in the
# navigation. Each entry can be configured in one of two ways. The first is:

View File

@@ -12,3 +12,7 @@ search.server = http://localhost:8080/solr/search
#All metadata fields that will not end up in the index, this is a comma separated list
index.ignore=dc.description.provenance
# index.ignore-variants = false
# index.ignore-authority = false
index.projection=dc.title,dc.contributor.*,dc.date.issued

View File

@@ -188,4 +188,5 @@
<property name="metadataField" value="dc.date.issued"/>
<property name="type" value="date"/>
</bean>
</beans>
</beans>

View File

@@ -22,4 +22,9 @@
<alias name="solrServiceResourceIndexPlugin" alias="org.dspace.discovery.SolrServiceResourceRestrictionPlugin"/>
<!-- Additional indexing plugin to implement the browse system via SOLR -->
<bean id="solrBrowseIndexer" scope="prototype"
class="org.dspace.browse.SolrBrowseCreateDAO">
</bean>
</beans>

File diff suppressed because it is too large Load Diff