VIVO-742 Refine the search interface
This commit is contained in:
parent
f4e81a7328
commit
cceca1659b
6 changed files with 64 additions and 98 deletions
|
@ -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);
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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 + "]";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue