Skip to content

Commit 2fff55b

Browse files
authored
Merge pull request #52 from netgen/NGSTACK-489-extra-solr-fields
NGSTACK-489 Extra solr fields
2 parents fe068cf + dae56dd commit 2fff55b

18 files changed

+746
-9
lines changed

docs/reference/extra_fields.rst

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
Extra fields from Solr
2+
======================
3+
4+
This feature allows you to extract additionally indexed Solr fields from each SearchHit in SearchResult. For example, you can index some fields from children content on the parent content and then get those fields during search (eg. children count).
5+
6+
.. note::
7+
8+
This feature is available only with the Solr search engine.
9+
10+
1. Usage
11+
~~~~~~~~
12+
13+
In order for this functionality to work, you have to use overridden `Netgen\EzPlatformSearchExtra\API\Values\Content\Search\Query` or `Netgen\EzPlatformSearchExtra\API\Values\Content\Search\LocationQuery` queries and use it's property `extraFields` to provide a list of additional fields that you want to extract from the Solr document. Those fields, if exist, and their values will appear in the `extraFields` property of each `SearchHit` object contained in the `SearchResult.`
14+
15+
2. Example
16+
~~~~~~~~~~
17+
18+
Example of a content field mapper:
19+
20+
.. code-block:: php
21+
22+
public function mapFields(SPIContent $content)
23+
{
24+
return [
25+
new Field(
26+
'extra_field_example',
27+
5,
28+
new IntegerField()
29+
),
30+
];
31+
}
32+
33+
Search example:
34+
35+
.. code-block:: php
36+
37+
/** @var \Netgen\EzPlatformSearchExtra\API\Values\Content\Search\Query $query **/
38+
$query = new Query();
39+
40+
$query->extraFields = [
41+
'extra_field_example_i',
42+
];
43+
44+
/** @var \Netgen\EzPlatformSiteApi\API\FindService $findService **/
45+
$searchResult = $findService->findContent($query);
46+
47+
/** @var \Netgen\EzPlatformSearchExtra\API\Values\Content\Search\SearchHit $searchHit **/
48+
foreach ($searchResult->searchHits as $searchHit) {
49+
var_dump($searchHit->extraFields);
50+
}
51+
52+
This will output the following data:
53+
54+
.. code-block:: shell
55+
56+
array(1) { ["extra_field_example_i"]=> int(5) }

docs/reference/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ Reference
99
random_sort
1010
subdocuments
1111
spellcheck_suggestions
12+
extra_fields
1213

1314
.. include:: /reference/map.rst.inc
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Netgen\EzPlatformSearchExtra\API\Values\Content\Search;
4+
5+
use eZ\Publish\API\Repository\Values\Content\LocationQuery as BaseLocationQuery;
6+
7+
class LocationQuery extends BaseLocationQuery
8+
{
9+
/**
10+
* List of additional fields that should be
11+
* extracted from the Solr document for each hit.
12+
*
13+
* @var string[]
14+
*/
15+
public $extraFields;
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Netgen\EzPlatformSearchExtra\API\Values\Content\Search;
4+
5+
use eZ\Publish\API\Repository\Values\Content\Query as BaseQuery;
6+
7+
class Query extends BaseQuery
8+
{
9+
/**
10+
* List of additional fields that should be
11+
* extracted from the Solr document for each hit.
12+
*
13+
* @var string[]
14+
*/
15+
public $extraFields;
16+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Netgen\EzPlatformSearchExtra\API\Values\Content\Search;
4+
5+
use eZ\Publish\API\Repository\Values\Content\Search\SearchHit as BaseSearchHit;
6+
7+
class SearchHit extends BaseSearchHit
8+
{
9+
/**
10+
* Additional fields from Solr document.
11+
*
12+
* @var array
13+
*/
14+
public $extraFields;
15+
}

lib/Core/Search/Solr/Handler.php

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,58 @@
22

33
namespace Netgen\EzPlatformSearchExtra\Core\Search\Solr;
44

5-
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\LogicalAnd;
6-
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\LogicalNot;
5+
use eZ\Publish\API\Repository\Values\Content\LocationQuery;
6+
use eZ\Publish\API\Repository\Values\Content\Query;
7+
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
8+
use EzSystems\EzPlatformSolrSearchEngine\DocumentMapper;
79
use EzSystems\EzPlatformSolrSearchEngine\Handler as BaseHandler;
810
use eZ\Publish\Core\Base\Exceptions\NotFoundException;
911

1012
class Handler extends BaseHandler
1113
{
14+
public function findContent(Query $query, array $languageFilter = array())
15+
{
16+
$query = clone $query;
17+
$query->filter = $query->filter ?: new Criterion\MatchAll();
18+
$query->query = $query->query ?: new Criterion\MatchAll();
19+
20+
$this->coreFilter->apply(
21+
$query,
22+
$languageFilter,
23+
DocumentMapper::DOCUMENT_TYPE_IDENTIFIER_CONTENT
24+
);
25+
26+
return $this->resultExtractor->extract(
27+
$this->gateway->findContent($query, $languageFilter),
28+
$query->facetBuilders,
29+
$query
30+
);
31+
}
32+
33+
public function findLocations(LocationQuery $query, array $languageFilter = array())
34+
{
35+
$query = clone $query;
36+
$query->query = $query->query ?: new Criterion\MatchAll();
37+
38+
$this->coreFilter->apply(
39+
$query,
40+
$languageFilter,
41+
DocumentMapper::DOCUMENT_TYPE_IDENTIFIER_LOCATION
42+
);
43+
44+
return $this->resultExtractor->extract(
45+
$this->gateway->findLocations($query, $languageFilter),
46+
$query->facetBuilders,
47+
$query
48+
);
49+
}
50+
1251
protected function deleteAllItemsWithoutAdditionalLocation($locationId)
1352
{
1453
$query = $this->prepareQuery();
15-
$query->filter = new LogicalAnd([
54+
$query->filter = new Criterion\LogicalAnd([
1655
$this->allItemsWithinLocation($locationId),
17-
new LogicalNot($this->allItemsWithinLocationWithAdditionalLocation($locationId)),
56+
new Criterion\LogicalNot($this->allItemsWithinLocationWithAdditionalLocation($locationId)),
1857
]);
1958

2059
$contentIds = $this->extractContentIds(
@@ -30,7 +69,7 @@ protected function deleteAllItemsWithoutAdditionalLocation($locationId)
3069
protected function updateAllElementsWithAdditionalLocation($locationId)
3170
{
3271
$query = $this->prepareQuery();
33-
$query->filter = new LogicalAnd([
72+
$query->filter = new Criterion\LogicalAnd([
3473
$this->allItemsWithinLocation($locationId),
3574
$this->allItemsWithinLocationWithAdditionalLocation($locationId),
3675
]);

lib/Core/Search/Solr/ResultExtractor.php

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
use EzSystems\EzPlatformSolrSearchEngine\ResultExtractor as BaseResultExtractor;
66
use Netgen\EzPlatformSearchExtra\Core\Search\Solr\API\FacetBuilder\RawFacetBuilder;
7+
use eZ\Publish\API\Repository\Values\Content\Query;
8+
use Netgen\EzPlatformSearchExtra\API\Values\Content\Search\Query as ExtraQuery;
9+
use Netgen\EzPlatformSearchExtra\API\Values\Content\Search\LocationQuery as ExtraLocationQuery;
10+
use Netgen\EzPlatformSearchExtra\API\Values\Content\Search\SearchHit;
711

812
/**
913
* This DocumentMapper implementation adds support for handling RawFacetBuilders.
@@ -12,10 +16,23 @@
1216
*/
1317
abstract class ResultExtractor Extends BaseResultExtractor
1418
{
15-
public function extract($data, array $facetBuilders = [])
19+
public function extract($data, array $facetBuilders = [], ?Query $query = null)
1620
{
1721
$searchResult = $this->extractSearchResult($data, $facetBuilders);
1822

23+
foreach ($searchResult->searchHits as $key => $searchHit) {
24+
$searchResult->searchHits[$key] = new SearchHit(get_object_vars($searchHit));
25+
$searchResult->searchHits[$key]->extraFields = [];
26+
27+
if (($query instanceof ExtraQuery || $query instanceof ExtraLocationQuery) && is_array($query->extraFields)) {
28+
$searchResult->searchHits[$key]->extraFields = $this->extractExtraFields(
29+
$data,
30+
$searchResult->searchHits[$key],
31+
$query->extraFields
32+
);
33+
}
34+
}
35+
1936
if (!isset($data->facets) || $data->facets->count === 0) {
2037
return $searchResult;
2138
}
@@ -57,4 +74,28 @@ function ($facetBuilder) {
5774
}
5875
);
5976
}
77+
78+
/**
79+
* @param mixed $data
80+
* @param \Netgen\EzPlatformSearchExtra\API\Values\Content\Search\SearchHit $searchHit
81+
* @param string[] $extraFields
82+
*
83+
* @return array
84+
*/
85+
private function extractExtraFields($data, SearchHit $searchHit, $extraFields)
86+
{
87+
$extractedExtraFields = [];
88+
foreach ($data->response->docs as $doc) {
89+
if ($doc->document_type_id === 'content' && $doc->content_id_id == $searchHit->valueObject->id
90+
|| $doc->document_type_id === 'location' && $doc->location_id == $searchHit->valueObject->id) {
91+
foreach ($extraFields as $extraField) {
92+
if (property_exists($doc, $extraField)) {
93+
$extractedExtraFields[$extraField] = $doc->{$extraField};
94+
}
95+
}
96+
}
97+
}
98+
99+
return $extractedExtraFields;
100+
}
60101
}

phpunit-integration-legacy.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
<exclude>tests/lib/Integration/API/IsFieldEmptyCriterionTest.php</exclude>
1717
<exclude>tests/lib/Integration/API/SubdocumentFieldSortClauseTest.php</exclude>
1818
<exclude>tests/lib/Integration/API/SubdocumentQueryCriterionTest.php</exclude>
19+
<exclude>tests/lib/Integration/API/FulltextSpellcheckCriterionTest.php</exclude>
20+
<exclude>tests/lib/Integration/API/ExtraFieldsTest.php</exclude>
1921
<exclude>tests/lib/Integration/Solr/RawFacetDomainTest.php</exclude>
2022
<exclude>tests/lib/Integration/Solr/RawFacetTest.php</exclude>
2123
</testsuite>

0 commit comments

Comments
 (0)