/**
* SolrQueryUtils.java
* Author: Philip Kahle (philip.kahle@uibk.ac.at)
*
* This file is part of PrestoPRIME Preservation Platform (P4).
*
* Copyright (C) 2009-2012 University of Innsbruck, Austria
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.prestoprime.search.util;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
import eu.prestoprime.search.SearchConstants;
import eu.prestoprime.search.util.Schema.P4FacetField;
import eu.prestoprime.search.util.Schema.P4SortField;
import eu.prestoprime.search.util.Schema.searchField;
/**
* Helper class containing methods for configuring a SolrQuery object
*
* @author Philip Kahle
*
*/
public class SolrQueryUtils {
private static final Logger LOGGER = Logger.getLogger(SolrQueryUtils.class);
/**
* Enable faceting on this solrQuery. Also sets the fields for faceting from
* the Hashmaps key. If this is already a subsequent query you have to put
* the selected facetValues to the appropriate value fields of the Hashmap
*
* @param solrQuery
* solrQuery object
* @param facets
* a HashMap containing facetFields and values as key and value
* respectively
*/
public static void setFacets(SolrQuery solrQuery, Map<P4FacetField, String> facets) {
solrQuery.setFacet(true).setFacetLimit(10).setFacetMinCount(2);
if (facets == null)
facets = getDefaultFacetMap();
for (Entry<P4FacetField, String> facet : facets.entrySet()) {
// enable faceting on this field
if (facet.getKey().getAssocField().getType().equals(Schema.FieldType.TDATE)) {
// rangefacet on all fields of type tdate
solrQuery.addDateRangeFacet(facet.getKey().getFieldName(), new Date(0), new Date(), SearchConstants.getString("dateRangeFacetGranularity"));
LOGGER.debug("Enable range faceting on field '" + facet.getKey().getFieldName() + "'");
} else {
solrQuery.addFacetField(facet.getKey().getFieldName());
LOGGER.debug("Enable faceting on field '" + facet.getKey().getFieldName() + "'");
}
// if there is already a value for filtering on this facet then add
// a filterquery for this
if (facet.getValue() != null && facet.getValue().length() > 0) {
LOGGER.debug("Set facet value '" + facet.getValue() + "' for field '" + facet.getKey().getFieldName() + "'");
solrQuery.addFilterQuery(facet.getKey().getFieldName() + ":" + facet.getValue());
}
}
}
/**
* Enable faceting on this solrQuery for all default facet fields.
*
* @param solrQuery
* solrQuery object
*/
public static void enableFacets(SolrQuery solrQuery) {
setFacets(solrQuery, getDefaultFacetMap());
}
/**
* Enable sorting on a specific field in descending order
*
* @param solrQuery
* solrQuery object to alter
* @param sortField
* the sortField (enumeration in Schema.java)
*/
public static void setSortField(SolrQuery solrQuery, P4SortField sortField) {
setSortField(solrQuery, sortField, false);
}
/**
* Enable sorting on a specific field in customizable order
*
* @param solrQuery
* solrQuery object to alter
* @param sortField
* the sortField (see enumeration in {@link Schema})
* @param sortAscending
*/
public static void setSortField(SolrQuery solrQuery, P4SortField sortField, boolean sortAscending) {
LOGGER.debug("Enable sorting on field '" + sortField.getFieldName() + "'");
LOGGER.debug(sortAscending ? "Order ASCENDING -> " + ORDER.asc.toString() : "Order DESCENDING -> " + ORDER.desc.toString());
solrQuery.setSortField(sortField.getFieldName(), sortAscending ? ORDER.asc : ORDER.desc);
}
/**
* Specify the chunk of search results to be returned which is needed for
* paging in the front-end.
*
* @param query
* @param from
* @param resultCount
*/
public static void setResultRange(SolrQuery query, int from, int resultCount) {
LOGGER.debug("Setting result range -> " + from + "-" + (from + resultCount));
query.setStart(from).setRows(resultCount);
}
/**
* Builds a Map containing all allowed FacetFields (see enumeration in
* {@link Schema}) with empty value fields.
*
* @return the map
*/
public static Map<P4FacetField, String> getDefaultFacetMap() {
Map<P4FacetField, String> facets = new HashMap<P4FacetField, String>();
for (P4FacetField facet : P4FacetField.values()) {
facets.put(facet, "");
}
return facets;
}
/**
* Enable Solr's Highlighting Component on this query object. Each search
* term is highlighted in all returned fields.
*
* @param solrQuery
*/
public static void enableHighlightAllFields(SolrQuery solrQuery) {
LOGGER.debug("Enable highlighting on all fields covered in catchAll field.");
enableHighlight(solrQuery, null);
}
/**
* Enable Solr's Highlighting Component on this query object. Search terms
* in the map (as values) are only highlighted in the belonging search
* fields.
*
* @param solrQuery
* @param fieldMap
*/
public static void enableHighlight(SolrQuery solrQuery, final Map<Schema.searchField, String> fieldMap) {
// enable highlighting on Query
solrQuery.setHighlight(true);
// unlimited fragment size and hightlights
solrQuery.setHighlightFragsize(0);
StringBuilder logMsg = new StringBuilder("Enable highlighting on fields: ");
// use these to set a start/end tag for highlights other than <em>
// (defined in Solr Config)
// solrQuery.setHighlightSimplePre(Constants.getString("HIGHLIGHT_PRE"));
// solrQuery.setHighlightSimplePost(Constants.getString("HIGHLIGHT_POST"));
if (fieldMap == null || fieldMap.isEmpty()) { // dismax query -> enable
// highlighting on all
// fields
solrQuery.set("hl.highlightMultiTerm", true);
for (searchField s : Schema.catchAll) {
solrQuery.addHighlightField(s.getFieldName());
logMsg.append(s.getFieldName() + ", ");
}
LOGGER.debug(logMsg.toString().substring(0, logMsg.length() - 2));
} else {
// highlight matching words in queried fields only
solrQuery.set("hl.usePhraseHighlighter", true);
solrQuery.setHighlightRequireFieldMatch(true);
for (Entry<Schema.searchField, String> e : fieldMap.entrySet()) {
// highlighting on range fields does no work. Just use text
// fields
if (e.getKey().getType().equals(Schema.FieldType.P4_TEXT) || e.getKey().getType().equals(Schema.FieldType.STRING)) {
logMsg.append(e.getKey().getFieldName() + ", ");
solrQuery.addHighlightField(e.getKey().getFieldName());
}
}
LOGGER.debug(logMsg.toString().substring(0, logMsg.length() - 2));
}
}
public static String getDateRangeFilter(String value) {
// createdate:[1976-03-06T23:59:59.999Z TO
// 1976-03-06T23:59:59.999Z+1YEAR]
return "[" + value + " TO " + value + SearchConstants.getString("dateRangeFacetGranularity") + "]";// +
// "-1DAY]";
}
}