From 1439a10d94b9d36bb7bf88c1c22d3ef451e84b3e Mon Sep 17 00:00:00 2001 From: Chris Hallberg <crhallberg@gmail.com> Date: Fri, 3 Jun 2016 08:57:17 -0400 Subject: [PATCH] More generic bulk facet retrieval, including Summon support. --- .../VuFind/src/VuFind/Search/Base/Results.php | 48 ++++++++++++++++ .../VuFind/src/VuFind/Search/Solr/Results.php | 27 +++++++-- .../src/VuFind/Search/Summon/Results.php | 55 +++++++++++++++++++ 3 files changed, 124 insertions(+), 6 deletions(-) diff --git a/module/VuFind/src/VuFind/Search/Base/Results.php b/module/VuFind/src/VuFind/Search/Base/Results.php index f693db99242..c6e4e109cf0 100644 --- a/module/VuFind/src/VuFind/Search/Base/Results.php +++ b/module/VuFind/src/VuFind/Search/Base/Results.php @@ -621,4 +621,52 @@ abstract class Results implements ServiceLocatorAwareInterface [$this->getOptions(), 'translate'], func_get_args() ); } + + /** + * Get complete facet counts for several index fields + * + * @param array $facetfields name of the Solr fields to return facets for + * @param bool $removeFilter Clear existing filters from selected fields (true) + * or retain them (false)? + * @param int $limit A limit for the number of facets returned, this + * may be useful for very large amounts of facets that can break the JSON parse + * method because of PHP out of memory exceptions (default = -1, no limit). + * @param string $facetSort A facet sort value to use (null to retain current) + * + * @return array an array with the facet values for each index field + */ + public function getFullFieldFacets($facetfields, $removeFilter = true, + $limit = -1, $facetSort = null + ) { + if (!method_exists($this, 'getPartialFieldFacets')) { + throw new \Exception('getPartialFieldFacets not implemented'); + } + $page = 1; + $facets = []; + do { + $facetpage = $this->getPartialFieldFacets( + $facetfields, $removeFilter, $limit, $facetSort, $page + ); + $nextfields = []; + foreach ($facetfields as $field) { + if (!empty($facetpage[$field]['data']['list'])) { + if (!isset($facets[$field])) { + $facets[$field] = $facetpage[$field]; + $facets[$field]['more'] = false; + } else { + $facets[$field]['data']['list'] = array_merge( + $facets[$field]['data']['list'], + $facetpage[$field]['data']['list'] + ); + } + if ($facetpage[$field]['more'] !== false) { + $nextfields[] = $field; + } + } + } + $facetfields = $nextfields; + $page++; + } while ($limit == -1 && !empty($facetfields)); + return $facets; + } } diff --git a/module/VuFind/src/VuFind/Search/Solr/Results.php b/module/VuFind/src/VuFind/Search/Solr/Results.php index bc6a1db1e3a..55793aff52e 100644 --- a/module/VuFind/src/VuFind/Search/Solr/Results.php +++ b/module/VuFind/src/VuFind/Search/Solr/Results.php @@ -294,11 +294,13 @@ class Results extends \VuFind\Search\Base\Results * may be useful for very large amounts of facets that can break the JSON parse * method because of PHP out of memory exceptions (default = -1, no limit). * @param string $facetSort A facet sort value to use (null to retain current) + * @param int $page 1 based. Offsets results by limit. + * @param bool $ored Whether or not facet is an OR facet or not * - * @return array an array with the facet values for each index field + * @return array list facet values for each index field with label and more bool */ - public function getFullFieldFacets($facetfields, $removeFilter = true, - $limit = -1, $facetSort = null + public function getPartialFieldFacets($facetfields, $removeFilter = true, + $limit = -1, $facetSort = null, $page = null, $ored = false ) { $clone = clone($this); $params = $clone->getParams(); @@ -306,11 +308,17 @@ class Results extends \VuFind\Search\Base\Results // Manipulate facet settings temporarily: $params->resetFacetConfig(); $params->setFacetLimit($limit); + if (null !== $page && $limit != -1) { + $offset = ($page - 1) * $limit; + $params->setFacetOffset($offset); + // Return limit plus one so we know there's another page + $params->setFacetLimit($limit + 1); + } if (null !== $facetSort) { $params->setFacetSort($facetSort); } foreach ($facetfields as $facetName) { - $params->addFacet($facetName); + $params->addFacet($facetName, null, $ored); // Clear existing filters for the selected field if necessary: if ($removeFilter) { @@ -335,8 +343,15 @@ class Results extends \VuFind\Search\Base\Results // Reformat into a hash: foreach ($result as $key => $value) { - unset($result[$key]); - $result[$key]['data'] = $value; + // Detect next page and crop results if necessary + $more = false; + if (isset($page) && count($value['list']) > 0 + && count($value['list']) == $limit + 1 + ) { + $more = true; + array_pop($value['list']); + } + $result[$key] = ['more' => $more, 'data' => $value]; } // Send back data: diff --git a/module/VuFind/src/VuFind/Search/Summon/Results.php b/module/VuFind/src/VuFind/Search/Summon/Results.php index e775eaece5b..33920481080 100644 --- a/module/VuFind/src/VuFind/Search/Summon/Results.php +++ b/module/VuFind/src/VuFind/Search/Summon/Results.php @@ -322,4 +322,59 @@ class Results extends \VuFind\Search\Base\Results { return $this->topicRecommendations; } + + /** + * Get complete facet counts for several index fields + * + * @param array $facetfields name of the Solr fields to return facets for + * @param bool $removeFilter Clear existing filters from selected fields (true) + * or retain them (false)? + * @param int $limit A limit for the number of facets returned, this + * may be useful for very large amounts of facets that can break the JSON parse + * method because of PHP out of memory exceptions (default = -1, no limit). + * @param string $facetSort A facet sort value to use (null to retain current) + * @param int $page 1 based. Offsets results by limit. + * + * @return array an array with the facet values for each index field + */ + public function getPartialFieldFacets($facetfields, $removeFilter = true, + $limit = -1, $facetSort = null, $page = null + ) { + $params = $this->getParams(); + $query = $params->getQuery(); + // No limit not implemented with Summon: cause page loop + if ($limit == -1) { + if ($page === null) { + $page = 1; + } + $limit = 50; + } + $params->resetFacetConfig(); + foreach ($facetfields as $facet) { + $params->addFacet($facet . ',or,' . $page . ',' . $limit); + } + $params = $params->getBackendParameters(); + $collection = $this->getSearchService()->search( + 'Summon', $query, 0, 0, $params + ); + + $facets = $collection->getFacets(); + $ret = []; + foreach ($facets as $data) { + if (in_array($data['displayName'], $facetfields)) { + $formatted = $this->formatFacetData($data); + $list = $formatted['counts']; + $ret[$data['displayName']] = [ + 'data' => [ + 'label' => $data['displayName'], + 'list' => $list, + ], + 'more' => null + ]; + } + } + + // Send back data: + return $ret; + } } -- GitLab