VIVO-742 Refine the search interface

This commit is contained in:
Jim Blake 2014-04-23 14:15:12 -04:00
parent f4e81a7328
commit cceca1659b
6 changed files with 64 additions and 98 deletions

View file

@ -327,8 +327,7 @@ public class VClassGroupCache implements IndexingEventListener {
SearchQuery query = searchEngine.createQuery(). SearchQuery query = searchEngine.createQuery().
setRows(0). setRows(0).
setQuery(VitroSearchTermNames.CLASSGROUP_URI + ":" + groupUri ). setQuery(VitroSearchTermNames.CLASSGROUP_URI + ":" + groupUri ).
setFaceting(true). //facet on type to get counts for classes in classgroup addFacetFields( facetOnField ). //facet on type to get counts for classes in classgroup
addFacetFields( facetOnField ).
setFacetMinCount(0); setFacetMinCount(0);
log.debug("query: " + query); log.debug("query: " + query);

View file

@ -3,7 +3,6 @@
package edu.cornell.mannlib.vitro.webapp.modules.searchEngine; package edu.cornell.mannlib.vitro.webapp.modules.searchEngine;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -20,118 +19,124 @@ public interface SearchQuery {
/** /**
* Set the text of the query. This will be parsed using Lucene query syntax. * Set the text of the query. This will be parsed using Lucene query syntax.
*
* @return this query
*/ */
SearchQuery setQuery(String query); SearchQuery setQuery(String query);
/** /**
* Where in the ordered list of result documents should the response begin? * Where in the ordered list of result documents should the response begin?
* That is, how many of the results should be skipped? (allows paging of * That is, how many of the results should be skipped? (allows paging of
* results) * results). The default is 0.
*
* @return this query
*/ */
SearchQuery setStart(int start); SearchQuery setStart(int start);
/** /**
* What is the maximum number of documents that will be returned from the * What is the maximum number of documents that will be returned from the
* query? * query? A negative value means no limit. The default is -1.
*
* @return this query
*/ */
SearchQuery setRows(int rows); SearchQuery setRows(int rows);
/** /**
* Which fields should be returned from the query? * Which fields should be returned from the query?
*
* @return this query
*/ */
SearchQuery addFields(String... names); SearchQuery addFields(String... names);
/** /**
* Which fields should be returned from the query? * Which fields should be returned from the query?
*
* @return this query
*/ */
SearchQuery addFields(Collection<String> names); SearchQuery addFields(Collection<String> names);
/** /**
* What field should be used to sort the results, and in what order? * What field should be used to sort the results, and in what order?
*
* @return this query
*/ */
SearchQuery addSortField(String name, Order order); SearchQuery addSortField(String name, Order order);
/** /**
* Restrict the results by thisw query. * Restrict the results by this query.
*
* @return this query
*/ */
SearchQuery addFilterQuery(String filterQuery); SearchQuery addFilterQuery(String filterQuery);
/** /**
* Restrict the results by these queries. * Restrict the results by these queries.
*
* @return this query
*/ */
SearchQuery addFilterQueries(String... filterQueries); SearchQuery addFilterQueries(String... filterQueries);
/**
* Should the results be faceted?
*/
SearchQuery setFaceting(boolean b);
/** /**
* What fields should be used to facet the results? * What fields should be used to facet the results?
*
* @return this query
*/ */
SearchQuery addFacetFields(String... fields); SearchQuery addFacetFields(String... fields);
/** /**
* Add queries that can be used to facet the results. * The maximum number of facet counts that will be returned from the query.
* The default is 100. A negative value means no limit.
*
* @return this query
*/ */
SearchQuery addFacetQueries(String... queries); SearchQuery setFacetLimit(int cnt);
/** /**
* Facet having fewer hits will be excluded from the list. * Facet having fewer hits will be excluded from the list. The default is 0.
*
* @return this query
*/ */
SearchQuery setFacetMinCount(int cnt); SearchQuery setFacetMinCount(int cnt);
/** /**
* Add a system-dependent parameter to the query. * @return The text of the query. May be empty, but never null.
*/
SearchQuery addParameter(String name, String... values);
/**
* Get the text of the query.
*/ */
String getQuery(); String getQuery();
int getStart(); int getStart();
/** /**
* A value of -1 means that no limit has been specified. * @return A negative value means that no limit has been specified.
*/ */
int getRows(); int getRows();
/** /**
* May return an empty set, but never null. * @return May return an empty set, but never null.
*/ */
Set<String> getFieldsToReturn(); Set<String> getFieldsToReturn();
/** /**
* May return an empty map, but never null. * @return May return an empty map, but never null.
*/ */
Map<String, SearchQuery.Order> getSortFields(); Map<String, SearchQuery.Order> getSortFields();
/** /**
* May return an empty set, but never null. * @return May return an empty set, but never null.
*/ */
Set<String> getFilters(); Set<String> getFilters();
boolean isFaceting();
/** /**
* May return an empty set, but never null. * @return May return an empty set, but never null.
*/ */
Set<String> getFacetFields(); Set<String> getFacetFields();
/** /**
* May return an empty set, but never null. * @return A negative value means that no limit has been specified.
*/ */
Set<String> getFacetQueries(); int getFacetLimit();
/** /**
* A value of -1 means that no limit has been specified. * @return A negative value means that no limit has been specified.
*/ */
int getFacetMinCount(); int getFacetMinCount();
/**
* May return an empty map, but never null.
*/
Map<String, List<String>> getParameterMap();
} }

View file

@ -484,22 +484,17 @@ public class PagedSearchController extends FreemarkerHttpServlet {
query.addFilterQuery(VitroSearchTermNames.CLASSGROUP_URI + ":\"" + classgroupParam + "\""); query.addFilterQuery(VitroSearchTermNames.CLASSGROUP_URI + ":\"" + classgroupParam + "\"");
//with ClassGroup filtering we want type facets //with ClassGroup filtering we want type facets
query.addParameter("facet","true"); query.addFacetFields(VitroSearchTermNames.RDFTYPE).setFacetLimit(-1);
query.addParameter("facet.limit","-1");
query.addParameter("facet.field",VitroSearchTermNames.RDFTYPE);
}else if ( ! StringUtils.isBlank(typeParam) ) { }else if ( ! StringUtils.isBlank(typeParam) ) {
// rdf:type filtering // rdf:type filtering
log.debug("Firing type query "); log.debug("Firing type query ");
log.debug("request.getParameter(type) is "+ typeParam); log.debug("request.getParameter(type) is "+ typeParam);
query.addFilterQuery(VitroSearchTermNames.RDFTYPE + ":\"" + typeParam + "\""); query.addFilterQuery(VitroSearchTermNames.RDFTYPE + ":\"" + typeParam + "\"");
//with type filtering we don't have facets. //with type filtering we don't have facets.
}else{ }else{
//When no filtering is set, we want ClassGroup facets //When no filtering is set, we want ClassGroup facets
query.addParameter("facet","true"); query.addFacetFields(VitroSearchTermNames.CLASSGROUP_URI).setFacetLimit(-1);
query.addParameter("facet.limit","-1");
query.addParameter("facet.field",VitroSearchTermNames.CLASSGROUP_URI);
} }
log.debug("Query = " + query.toString()); log.debug("Query = " + query.toString());

View file

@ -2,13 +2,11 @@
package edu.cornell.mannlib.vitro.webapp.searchengine.base; package edu.cornell.mannlib.vitro.webapp.searchengine.base;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -26,13 +24,10 @@ public class BaseSearchQuery implements SearchQuery {
private final Map<String, SearchQuery.Order> sortFields = new HashMap<>(); private final Map<String, SearchQuery.Order> sortFields = new HashMap<>();
private final Set<String> filters = new HashSet<>(); private final Set<String> filters = new HashSet<>();
private boolean faceting;
private final Set<String> facetFields = new HashSet<>(); private final Set<String> facetFields = new HashSet<>();
private final Set<String> facetQueries = new HashSet<>(); private int facetLimit = 100;
private int facetMinCount = -1; private int facetMinCount = -1;
private final Map<String, List<String>> parameterMap = new HashMap<>();
@Override @Override
public SearchQuery setQuery(String query) { public SearchQuery setQuery(String query) {
this.queryText = query; this.queryText = query;
@ -80,12 +75,6 @@ public class BaseSearchQuery implements SearchQuery {
return this; return this;
} }
@Override
public SearchQuery setFaceting(boolean b) {
this.faceting = b;
return this;
}
@Override @Override
public SearchQuery addFacetFields(String... fields) { public SearchQuery addFacetFields(String... fields) {
facetFields.addAll(Arrays.asList(fields)); facetFields.addAll(Arrays.asList(fields));
@ -93,8 +82,8 @@ public class BaseSearchQuery implements SearchQuery {
} }
@Override @Override
public SearchQuery addFacetQueries(String... queries) { public SearchQuery setFacetLimit(int cnt) {
facetQueries.addAll(Arrays.asList(queries)); facetLimit = cnt;
return this; return this;
} }
@ -104,13 +93,6 @@ public class BaseSearchQuery implements SearchQuery {
return this; return this;
} }
@Override
public SearchQuery addParameter(String name, String... values) {
parameterMap.put(name, Collections.unmodifiableList(new ArrayList<>(
Arrays.asList(values))));
return this;
}
@Override @Override
public String getQuery() { public String getQuery() {
return queryText; return queryText;
@ -141,19 +123,14 @@ public class BaseSearchQuery implements SearchQuery {
return Collections.unmodifiableSet(filters); return Collections.unmodifiableSet(filters);
} }
@Override
public boolean isFaceting() {
return faceting;
}
@Override @Override
public Set<String> getFacetFields() { public Set<String> getFacetFields() {
return Collections.unmodifiableSet(facetFields); return Collections.unmodifiableSet(facetFields);
} }
@Override @Override
public Set<String> getFacetQueries() { public int getFacetLimit() {
return Collections.unmodifiableSet(facetQueries); return facetLimit;
} }
@Override @Override
@ -161,19 +138,13 @@ public class BaseSearchQuery implements SearchQuery {
return facetMinCount; return facetMinCount;
} }
@Override
public Map<String, List<String>> getParameterMap() {
return Collections.unmodifiableMap(parameterMap);
}
@Override @Override
public String toString() { public String toString() {
return "BaseSearchQuery[queryText=" + queryText + ", start=" + start return "BaseSearchQuery[queryText=" + queryText + ", start=" + start
+ ", rows=" + rows + ", fieldsToReturn=" + fieldsToReturn + ", rows=" + rows + ", fieldsToReturn=" + fieldsToReturn
+ ", sortFields=" + sortFields + ", filters=" + filters + ", sortFields=" + sortFields + ", filters=" + filters
+ ", faceting=" + faceting + ", facetFields=" + facetFields + ", facetFields=" + facetFields + ", facetLimit=" + facetLimit
+ ", facetQueries=" + facetQueries + ", facetMinCount=" + ", facetMinCount=" + facetMinCount + "]";
+ facetMinCount + ", parameterMap=" + parameterMap + "]";
} }
} }

View file

@ -102,14 +102,17 @@ public class SolrConversionUtils {
solrQuery.addFilterQuery(filter); solrQuery.addFilterQuery(filter);
} }
solrQuery.setFacet(query.isFaceting()); if (!query.getFacetFields().isEmpty()) {
solrQuery.setFacet(true);
}
for (String facetField : query.getFacetFields()) { for (String facetField : query.getFacetFields()) {
solrQuery.addFacetField(facetField); solrQuery.addFacetField(facetField);
} }
for (String facetQuery : query.getFacetQueries()) { int facetLimit = query.getFacetLimit();
solrQuery.addFacetQuery(facetQuery); if (facetLimit >= 0) {
solrQuery.setFacetLimit(facetLimit);
} }
int minCount = query.getFacetMinCount(); int minCount = query.getFacetMinCount();
@ -117,13 +120,6 @@ public class SolrConversionUtils {
solrQuery.setFacetMinCount(minCount); solrQuery.setFacetMinCount(minCount);
} }
Map<String, List<String>> parameterMap = query.getParameterMap();
for (String parameterName : parameterMap.keySet()) {
String[] values = parameterMap.get(parameterName).toArray(
new String[0]);
solrQuery.add(parameterName, values);
}
return solrQuery; return solrQuery;
} }

View file

@ -77,7 +77,7 @@ public class SearchIndexerSetup implements ServletContextListener {
SearchEngine searchEngine = ApplicationUtils.instance().getSearchEngine(); SearchEngine searchEngine = ApplicationUtils.instance().getSearchEngine();
try { try {
/* set up the individual to solr doc translation */ /* set up the individual to search doc translation */
OntModel jenaOntModel = ModelAccess.on(context).getJenaOntModel(); OntModel jenaOntModel = ModelAccess.on(context).getJenaOntModel();
OntModel displayModel = ModelAccess.on(context).getDisplayModel(); OntModel displayModel = ModelAccess.on(context).getDisplayModel();
@ -100,13 +100,13 @@ public class SearchIndexerSetup implements ServletContextListener {
List<SearchIndexExcluder> searchIndexExcludesFromContext = (List<SearchIndexExcluder>) context List<SearchIndexExcluder> searchIndexExcludesFromContext = (List<SearchIndexExcluder>) context
.getAttribute("SearchIndexExcludes"); .getAttribute("SearchIndexExcludes");
IndividualToSearchDocument indToSolrDoc = setupTransltion( IndividualToSearchDocument indToSearchDoc = setupTranslation(
jenaOntModel, displayModel, jenaOntModel, displayModel,
RDFServiceUtils.getRDFServiceFactory(context), RDFServiceUtils.getRDFServiceFactory(context),
modifiersFromContext, searchIndexExcludesFromContext); modifiersFromContext, searchIndexExcludesFromContext);
/* setup solr indexer */ /* setup search indexer */
SearchIndexer solrIndexer = new SearchIndexer(searchEngine, indToSolrDoc); SearchIndexer searchIndexer = new SearchIndexer(searchEngine, indToSearchDoc);
// This is where the builder gets the list of places to try to // This is where the builder gets the list of places to try to
// get objects to index. It is filtered so that non-public text // get objects to index. It is filtered so that non-public text
@ -123,7 +123,7 @@ public class SearchIndexerSetup implements ServletContextListener {
.getList(rdfService, wadf.getIndividualDao()); .getList(rdfService, wadf.getIndividualDao());
// Make the IndexBuilder // Make the IndexBuilder
IndexBuilder builder = new IndexBuilder(solrIndexer, wadf, IndexBuilder builder = new IndexBuilder(searchIndexer, wadf,
uriFinders); uriFinders);
// Save it to the servlet context so we can access it later in the // Save it to the servlet context so we can access it later in the
// webapp. // webapp.
@ -135,9 +135,9 @@ public class SearchIndexerSetup implements ServletContextListener {
SearchReindexingListener srl = new SearchReindexingListener(builder); SearchReindexingListener srl = new SearchReindexingListener(builder);
ModelContext.registerListenerForChanges(ctx, srl); ModelContext.registerListenerForChanges(ctx, srl);
ss.info(this, "Setup of Solr index completed."); ss.info(this, "Setup of search indexer completed.");
} catch (Throwable e) { } catch (Throwable e) {
ss.fatal(this, "could not setup local solr server", e); ss.fatal(this, "could not setup search engine", e);
} }
} }
@ -151,7 +151,7 @@ public class SearchIndexerSetup implements ServletContextListener {
} }
public static IndividualToSearchDocument setupTransltion( public static IndividualToSearchDocument setupTranslation(
OntModel jenaOntModel, Model displayModel, OntModel jenaOntModel, Model displayModel,
RDFServiceFactory rdfServiceFactory, RDFServiceFactory rdfServiceFactory,
List<DocumentModifier> modifiersFromContext, List<DocumentModifier> modifiersFromContext,