Merge pull request #10138 from DSpace/backport-10057-to-dspace-7_x

[Port dspace-7_x] Add limit, offset, and total facet count to Solr query for the metadata browse index
This commit is contained in:
Tim Donohue
2024-12-18 12:57:36 -06:00
committed by GitHub
4 changed files with 72 additions and 35 deletions

View File

@@ -422,9 +422,6 @@ public class BrowseEngine {
} }
} }
// this is the total number of results in answer to the query
int total = getTotalResults(true);
// set the ordering field (there is only one option) // set the ordering field (there is only one option)
dao.setOrderField("sort_value"); dao.setOrderField("sort_value");
@@ -444,6 +441,9 @@ public class BrowseEngine {
dao.setOffset(offset); dao.setOffset(offset);
dao.setLimit(scope.getResultsPerPage()); dao.setLimit(scope.getResultsPerPage());
// this is the total number of results in answer to the query
int total = getTotalResults(true);
// Holder for the results // Holder for the results
List<String[]> results = null; List<String[]> results = null;
@@ -680,33 +680,9 @@ public class BrowseEngine {
// tell the browse query whether we are distinct // tell the browse query whether we are distinct
dao.setDistinct(distinct); dao.setDistinct(distinct);
// ensure that the select is set to "*"
String[] select = {"*"};
dao.setCountValues(select);
// FIXME: it would be nice to have a good way of doing this in the DAO
// now reset all of the fields that we don't want to have constraining
// our count, storing them locally to reinstate later
String focusField = dao.getJumpToField();
String focusValue = dao.getJumpToValue();
int limit = dao.getLimit();
int offset = dao.getOffset();
dao.setJumpToField(null);
dao.setJumpToValue(null);
dao.setLimit(-1);
dao.setOffset(-1);
// perform the query and get the result // perform the query and get the result
int count = dao.doCountQuery(); int count = dao.doCountQuery();
// now put back the values we removed for this method
dao.setJumpToField(focusField);
dao.setJumpToValue(focusValue);
dao.setLimit(limit);
dao.setOffset(offset);
dao.setCountValues(null);
log.debug(LogHelper.getHeader(context, "get_total_results_return", "return=" + count)); log.debug(LogHelper.getHeader(context, "get_total_results_return", "return=" + count));
return count; return count;

View File

@@ -13,6 +13,8 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.solr.client.solrj.util.ClientUtils; import org.apache.solr.client.solrj.util.ClientUtils;
@@ -180,18 +182,33 @@ public class SolrBrowseDAO implements BrowseDAO {
addDefaultFilterQueries(query); addDefaultFilterQueries(query);
if (distinct) { if (distinct) {
DiscoverFacetField dff; DiscoverFacetField dff;
// To get the number of distinct values we use the next "json.facet" query param
// {"entries_count": {"type":"terms","field": "<fieldName>_filter", "limit":0, "numBuckets":true}}"
ObjectNode jsonFacet = JsonNodeFactory.instance.objectNode();
ObjectNode entriesCount = JsonNodeFactory.instance.objectNode();
entriesCount.put("type", "terms");
entriesCount.put("field", facetField + "_filter");
entriesCount.put("limit", 0);
entriesCount.put("numBuckets", true);
jsonFacet.set("entries_count", entriesCount);
if (StringUtils.isNotBlank(startsWith)) { if (StringUtils.isNotBlank(startsWith)) {
dff = new DiscoverFacetField(facetField, dff = new DiscoverFacetField(facetField,
DiscoveryConfigurationParameters.TYPE_TEXT, -1, DiscoveryConfigurationParameters.TYPE_TEXT, limit,
DiscoveryConfigurationParameters.SORT.VALUE, startsWith); DiscoveryConfigurationParameters.SORT.VALUE, startsWith, offset);
// Add the prefix to the json facet query
entriesCount.put("prefix", startsWith);
} else { } else {
dff = new DiscoverFacetField(facetField, dff = new DiscoverFacetField(facetField,
DiscoveryConfigurationParameters.TYPE_TEXT, -1, DiscoveryConfigurationParameters.TYPE_TEXT, limit,
DiscoveryConfigurationParameters.SORT.VALUE); DiscoveryConfigurationParameters.SORT.VALUE, offset);
} }
query.addFacetField(dff); query.addFacetField(dff);
query.setFacetMinCount(1); query.setFacetMinCount(1);
query.setMaxResults(0); query.setMaxResults(0);
query.addProperty("json.facet", jsonFacet.toString());
} else { } else {
query.setMaxResults(limit/* > 0 ? limit : 20*/); query.setMaxResults(limit/* > 0 ? limit : 20*/);
if (offset > 0) { if (offset > 0) {
@@ -248,8 +265,7 @@ public class SolrBrowseDAO implements BrowseDAO {
DiscoverResult resp = getSolrResponse(); DiscoverResult resp = getSolrResponse();
int count = 0; int count = 0;
if (distinct) { if (distinct) {
List<FacetResult> facetResults = resp.getFacetResult(facetField); count = (int) resp.getTotalEntries();
count = facetResults.size();
} else { } else {
// we need to cast to int to respect the BrowseDAO contract... // we need to cast to int to respect the BrowseDAO contract...
count = (int) resp.getTotalSearchResults(); count = (int) resp.getTotalSearchResults();
@@ -266,8 +282,8 @@ public class SolrBrowseDAO implements BrowseDAO {
DiscoverResult resp = getSolrResponse(); DiscoverResult resp = getSolrResponse();
List<FacetResult> facet = resp.getFacetResult(facetField); List<FacetResult> facet = resp.getFacetResult(facetField);
int count = doCountQuery(); int count = doCountQuery();
int start = offset > 0 ? offset : 0; int start = 0;
int max = limit > 0 ? limit : count; //if negative, return everything int max = facet.size();
List<String[]> result = new ArrayList<>(); List<String[]> result = new ArrayList<>();
if (ascending) { if (ascending) {
for (int i = start; i < (start + max) && i < count; i++) { for (int i = start; i < (start + max) && i < count; i++) {

View File

@@ -32,6 +32,9 @@ public class DiscoverResult {
private List<IndexableObject> indexableObjects; private List<IndexableObject> indexableObjects;
private Map<String, List<FacetResult>> facetResults; private Map<String, List<FacetResult>> facetResults;
// Total count of facet entries calculated for a metadata browsing query
private long totalEntries;
/** /**
* A map that contains all the documents sougth after, the key is a string representation of the Indexable Object * A map that contains all the documents sougth after, the key is a string representation of the Indexable Object
*/ */
@@ -64,6 +67,14 @@ public class DiscoverResult {
this.totalSearchResults = totalSearchResults; this.totalSearchResults = totalSearchResults;
} }
public long getTotalEntries() {
return totalEntries;
}
public void setTotalEntries(long totalEntries) {
this.totalEntries = totalEntries;
}
public int getStart() { public int getStart() {
return start; return start;
} }

View File

@@ -1055,6 +1055,8 @@ public class SolrServiceImpl implements SearchService, IndexingService {
} }
//Resolve our facet field values //Resolve our facet field values
resolveFacetFields(context, query, result, skipLoadingResponse, solrQueryResponse); resolveFacetFields(context, query, result, skipLoadingResponse, solrQueryResponse);
//Add total entries count for metadata browsing
resolveEntriesCount(result, solrQueryResponse);
} }
// If any stale entries are found in the current page of results, // If any stale entries are found in the current page of results,
// we remove those stale entries and rerun the same query again. // we remove those stale entries and rerun the same query again.
@@ -1080,7 +1082,39 @@ public class SolrServiceImpl implements SearchService, IndexingService {
return result; return result;
} }
/**
* Stores the total count of entries for metadata index browsing. The count is calculated by the
* <code>json.facet</code> parameter with the following value:
*
* <pre><code>
* {
* "entries_count": {
* "type": "terms",
* "field": "facetNameField_filter",
* "limit": 0,
* "prefix": "prefix_value",
* "numBuckets": true
* }
* }
* </code></pre>
*
* This value is returned in the <code>facets</code> field of the Solr response.
*
* @param result DiscoverResult object where the total entries count will be stored
* @param solrQueryResponse QueryResponse object containing the solr response
*/
private void resolveEntriesCount(DiscoverResult result, QueryResponse solrQueryResponse) {
Object facetsObj = solrQueryResponse.getResponse().get("facets");
if (facetsObj instanceof NamedList) {
NamedList<Object> facets = (NamedList<Object>) facetsObj;
Object bucketsInfoObj = facets.get("entries_count");
if (bucketsInfoObj instanceof NamedList) {
NamedList<Object> bucketsInfo = (NamedList<Object>) bucketsInfoObj;
result.setTotalEntries((int) bucketsInfo.get("numBuckets"));
}
}
}
private void resolveFacetFields(Context context, DiscoverQuery query, DiscoverResult result, private void resolveFacetFields(Context context, DiscoverQuery query, DiscoverResult result,
boolean skipLoadingResponse, QueryResponse solrQueryResponse) throws SQLException { boolean skipLoadingResponse, QueryResponse solrQueryResponse) throws SQLException {