Smart facet value escaping

This commit is contained in:
Mathieu Darse
2015-03-19 13:38:20 +01:00
parent a6d1a275a9
commit b1a03ae566
3 changed files with 23 additions and 11 deletions

View File

@@ -20,6 +20,8 @@ use Alchemy\Phrasea\SearchEngine\Elastic\IndexerSubscriber;
use Alchemy\Phrasea\SearchEngine\Elastic\Indexer\RecordIndexer; use Alchemy\Phrasea\SearchEngine\Elastic\Indexer\RecordIndexer;
use Alchemy\Phrasea\SearchEngine\Elastic\Indexer\TermIndexer; use Alchemy\Phrasea\SearchEngine\Elastic\Indexer\TermIndexer;
use Alchemy\Phrasea\SearchEngine\Elastic\RecordHelper; use Alchemy\Phrasea\SearchEngine\Elastic\RecordHelper;
use Alchemy\Phrasea\SearchEngine\Elastic\Search\Escaper;
use Alchemy\Phrasea\SearchEngine\Elastic\Search\FacetsResponse;
use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryParser; use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryParser;
use Alchemy\Phrasea\SearchEngine\Elastic\Thesaurus; use Alchemy\Phrasea\SearchEngine\Elastic\Thesaurus;
use Alchemy\Phrasea\SearchEngine\Phrasea\PhraseaEngine; use Alchemy\Phrasea\SearchEngine\Phrasea\PhraseaEngine;
@@ -67,10 +69,17 @@ class SearchEngineServiceProvider implements ServiceProviderInterface
return new ElasticSearchEngine( return new ElasticSearchEngine(
$app, $app,
$app['elasticsearch.client'], $app['elasticsearch.client'],
$app['elasticsearch.options']['index'] $app['elasticsearch.options']['index'],
$app['locales.available'],
$app['elasticsearch.record_helper'],
$app['elasticsearch.facets_response.factory']
); );
}); });
$app['elasticsearch.facets_response.factory'] = $app->protect(function (array $response) use ($app) {
return new FacetsResponse(new Excaper(), $response);
});
/* Indexer related services */ /* Indexer related services */

View File

@@ -13,6 +13,7 @@ namespace Alchemy\Phrasea\SearchEngine\Elastic;
use Alchemy\Phrasea\SearchEngine\Elastic\Indexer\RecordIndexer; use Alchemy\Phrasea\SearchEngine\Elastic\Indexer\RecordIndexer;
use Alchemy\Phrasea\SearchEngine\Elastic\Indexer\TermIndexer; use Alchemy\Phrasea\SearchEngine\Elastic\Indexer\TermIndexer;
use Alchemy\Phrasea\SearchEngine\Elastic\RecordHelper;
use Alchemy\Phrasea\SearchEngine\Elastic\Search\FacetsResponse; use Alchemy\Phrasea\SearchEngine\Elastic\Search\FacetsResponse;
use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryContext; use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryContext;
use Alchemy\Phrasea\SearchEngine\SearchEngineInterface; use Alchemy\Phrasea\SearchEngine\SearchEngineInterface;
@@ -39,12 +40,13 @@ class ElasticSearchEngine implements SearchEngineInterface
private $locales; private $locales;
private $recordHelper; private $recordHelper;
public function __construct(Application $app, Client $client, $indexName) public function __construct(Application $app, Client $client, $indexName, array $locales, RecordHelper $recordHelper, Closure $facetsResponseFactory)
{ {
$this->app = $app; $this->app = $app;
$this->client = $client; $this->client = $client;
$this->locales = array_keys($app['locales.available']); $this->locales = array_keys($locales);
$this->recordHelper = $this->app['elasticsearch.record_helper']; $this->recordHelper = $recordHelper;
$this->facetsResponseFactory = $facetsResponseFactory;
if ('' === trim($indexName)) { if ('' === trim($indexName)) {
throw new \InvalidArgumentException('The provided index name is invalid.'); throw new \InvalidArgumentException('The provided index name is invalid.');
@@ -292,7 +294,7 @@ class ElasticSearchEngine implements SearchEngineInterface
$results[] = ElasticsearchRecordHydrator::hydrate($hit['_source'], $n++); $results[] = ElasticsearchRecordHydrator::hydrate($hit['_source'], $n++);
} }
$facets = new FacetsResponse($res); $facets = $this->facetsResponseFactory->__invoke($res);
$query['ast'] = $this->app['query_parser']->parse($string)->dump(); $query['ast'] = $this->app['query_parser']->parse($string)->dump();
$query['query_main'] = $recordQuery; $query['query_main'] = $recordQuery;

View File

@@ -7,10 +7,13 @@ use JsonSerializable;
class FacetsResponse implements JsonSerializable class FacetsResponse implements JsonSerializable
{ {
private $escaper;
private $facets = array(); private $facets = array();
public function __construct(array $response) public function __construct(Escaper $escaper, array $response)
{ {
$this->escaper = $escaper;
if (!isset($response['aggregations'])) { if (!isset($response['aggregations'])) {
return; return;
} }
@@ -47,12 +50,10 @@ class FacetsResponse implements JsonSerializable
private function buildQuery($name, $value) private function buildQuery($name, $value)
{ {
// Strip double quotes from values to prevent broken queries $value = $this->escaper->escapeWord($value);
$value = str_replace('/"/u', ' ', $value);
// TODO escape value when escaping is supported in query parser
return ($name === 'Collection') ? return ($name === 'Collection') ?
sprintf('collection:"%s"', $value) : sprintf('collection:%s', $value) :
sprintf('"%s" IN %s', $value, $name); sprintf('%s IN %s', $value, $name);
} }
private function throwAggregationResponseError() private function throwAggregationResponseError()