Skip to content

Commit

Permalink
Add new serach criterion to allow proper replication of ezfind searches
Browse files Browse the repository at this point in the history
  • Loading branch information
gggeek committed Dec 18, 2018
1 parent 729691d commit 42bbe26
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 5 deletions.
19 changes: 19 additions & 0 deletions API/Repository/Values/Content/Query/Criterion/EzFindText.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Kaliop\EzFindSearchEngineBundle\API\Repository\Values\Content\Query\Criterion;

use eZ\Publish\API\Repository\Values\Content\Query\Criterion as BaseCriterion;

/**
* Full-text search criterion, based on eZFind configuration.
* When this criterion is used (NB: as part of a query's `query`, not `filter`), the given text will be matched against
* all content fields indexed in Solr as per eZFind configuration (including field boosts etc...)
* Note: when using the FullTextr criterion instead of this one, matching is done against the `ezf_df_text` Solr field
*/
class EzFindText extends BaseCriterion
{
public function __construct($value)
{
$this->value = $value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace Kaliop\EzFindSearchEngineBundle\Core\Persistence\eZFind\Content\Search\Common\Gateway\CriterionHandler;

use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
use Kaliop\EzFindSearchEngineBundle\Core\Persistence\eZFind\Content\Search\Common\Gateway\CriteriaConverter;
use Kaliop\EzFindSearchEngineBundle\Core\Persistence\eZFind\Content\Search\Common\Gateway\CriterionHandler;
use Kaliop\EzFindSearchEngineBundle\API\Repository\Values\Content\Query\Criterion\EzFindText as EzFindTextCriterion;

class EzFindText extends CriterionHandler
{
/**
* @inheritdoc
*/
public function accept(Criterion $criterion)
{
return $criterion instanceof EzFindTextCriterion;
}

/**
* If the full-text search contain wildcard search, build correct wildcard query
* with non-truncated words boosted.
*
* @inheritdoc
*/
public function handle(CriteriaConverter $converter, Criterion $criterion)
{
$value = trim($criterion->value);

if (preg_match('/^".+"$/', $value)) {
// Quoted-string query: escape everything but the outher quotes
$value = '"' . $this->escapeValue(substr($value, 1, -1)) . '"';

} else if (preg_match('/(^\*|\*$)/', $value)) {
// Wildcard query: make the exact match stronger than the wildcard

// @bug we do not support wildcard chars in the middle of phrases

$value = $this->escapeValue($value);

// Escape spaces
$value = str_replace(' ', '\\ ', $value);

// wildcard match: un-escape wildcard char
$wildcard = str_replace('\\*', '*', $value);

// Non-wildcard match
$value = trim($value, '*');
$value = rtrim($value, '\\');

$value = $value . '^2 OR ' . $wildcard;

} else {
// plain query
$value = $this->escapeValue($value);
}

return $value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public function handle(CriteriaConverter $converter, Criterion $criterion)
$value = '"' . $this->escapeValue(substr($value, 1, -1)) . '"';

} else if (preg_match('/(^\*|\*$)/', $value)) {
// Wildcard query: make the exacth match stronger than the wildcard
// Wildcard query: make the exact match stronger than the wildcard

// @bug we do not support wildcard chars in the middle of phrases

Expand Down
25 changes: 21 additions & 4 deletions Core/Repository/SearchService.php
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ protected function performSearch(
$this->initializeQueryLimit($query);

$searchParameters = $this->getLegacySearchParameters($query, $fieldFilters, $filterOnUserPermissions, $returnType);

//var_dump($searchParameters);
/** @var array $searchResult */
$searchResult = $this->getLegacyKernel()->runCallback(
function () use ($searchParameters) {
Expand Down Expand Up @@ -315,7 +315,7 @@ protected function getLegacySearchParameters(Query $query, array $fieldFilters,
$scoreSort = true;
}
}

//var_dump($query->criterion);die();
$criterionFilter = array();
if ($query->criterion) {
$criterionFilter = $this->extractFilter($query->criterion);
Expand All @@ -330,7 +330,10 @@ protected function getLegacySearchParameters(Query $query, array $fieldFilters,
$searchParameters['facet'] = $this->extractFacet($query->facetBuilders);
}

if ($scoreSort) {
if ($this->isEzFindCriterion($query->criterion)) {
$searchParameters['query'] = reset($criterionFilter);
$searchParameters['filter'] = $filterFilter;
} elseif ($scoreSort) {
// since we are sorting by score, we need to generate the solr query, as that is what is used to calculate score
$searchParameters['query'] = $this->filterCriteriaConverter->generateQueryString($criterionFilter);
$searchParameters['filter'] = $filterFilter;
Expand Down Expand Up @@ -389,6 +392,20 @@ protected function getReturnType(Query $query, $forceReturnType = null)
return ($query instanceof KaliopQuery && $query->returnType !== null) ? $query->returnType : $this->defaultReturnType;
}

/**
* Returns true if there is a single search criterion of type EzFindText
* @param Query\Criterion|Query\Criterion[] $criteria $criteria
* @return bool
*/
protected function isEzFindCriterion($criteria)
{
if (!is_array($criteria)) {
$criteria = array($criteria);
}

return (count($criteria) == 1 && $criteria[0] instanceof KaliopQuery\Criterion\EzFindText);
}

/**
* @param Query\Criterion|Query\Criterion[] $criteria
* @return array
Expand Down Expand Up @@ -447,7 +464,7 @@ protected function throwIfSearchError($searchResult)
if (!is_array($searchResult)) {
throw new eZFindException('The legacy search result is not an array');
}

//var_dump($searchResult);die();
if (isset($searchResult['SearchExtras']) && $searchResult['SearchExtras'] instanceof ezfSearchResultInfo) {
$errors = $searchResult['SearchExtras']->attribute('error');
/// @todo what if $errors it is an empty string, an array with unexepcted members or not even an array ?
Expand Down
5 changes: 5 additions & 0 deletions Resources/config/handlers/criteria.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ services:
tags:
- {name: ezfind_search_engine.content.criterion_handler.filter}

ezfind_search_engine.content.criterion_handler.ezfind_text:
class: Kaliop\EzFindSearchEngineBundle\Core\Persistence\eZFind\Content\Search\Common\Gateway\CriterionHandler\EzFindText
tags:
- {name: ezfind_search_engine.content.criterion_handler.filter}

ezfind_search_engine.content.criterion_handler.location_id:
class: Kaliop\EzFindSearchEngineBundle\Core\Persistence\eZFind\Content\Search\Common\Gateway\CriterionHandler\LocationId
tags:
Expand Down
3 changes: 3 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
- fulltext: might currently differ
- objectstateid: what happens when many states are passed in?

* check what happens when an ezfindtext criterion is used in the 'filter' member of a query, or when it is used together
with other filters

* check list of all missing criteria converters compared to std search service (for Content searches)
- contenttypegroup: can not do
- datemetadata: fails with operator IN
Expand Down
18 changes: 18 additions & 0 deletions WHATSNEW.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
Version 1.4
===========

* New: a new Query Criterion, `EzFindText`, can now be used to fully emulated legacy 'ezfind searches', i.e. do a
full-text search across all indexed content fields, instead of matching the `ezf_df_text` field as is done when using
a `FullText` criterion. This can greatly improve relevancy sorting.

Ex:

use Kaliop\EzFindSearchEngineBundle\API\Repository\Values\Content\Query\Criterion\EzFindText;
use Kaliop\EzFindSearchEngineBundle\API\Repository\Values\Content\Query\SortClause\Score;
...
$query->query = new EzFindText('hello world');
$query->sortClauses = [new Score('descending')];

*NB* the `EzFindText` criterion should be used as unique member of your query's `query` member.
When using it, use the query's `filter` member to add any other criteria.

Version 1.3
===========

Expand Down

0 comments on commit 42bbe26

Please sign in to comment.