Commit 853b566e authored by Markus Kalkbrenner's avatar Markus Kalkbrenner Committed by GitHub

Stream expression support (#581)

added basic support dor Solr Cloud stream expressions
parent 20ebb3c4
...@@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ...@@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased] ## [Unreleased]
### Added ### Added
- Basic support for Solr Cloud stream expressions
### Changed ### Changed
......
...@@ -87,6 +87,11 @@ class Client extends Configurable implements ClientInterface ...@@ -87,6 +87,11 @@ class Client extends Configurable implements ClientInterface
*/ */
const QUERY_SUGGESTER = 'suggester'; const QUERY_SUGGESTER = 'suggester';
/**
* Querytype stream.
*/
const QUERY_STREAM = 'stream';
/** /**
* Querytype extract. * Querytype extract.
*/ */
...@@ -124,6 +129,7 @@ class Client extends Configurable implements ClientInterface ...@@ -124,6 +129,7 @@ class Client extends Configurable implements ClientInterface
self::QUERY_TERMS => 'Solarium\QueryType\Terms\Query', self::QUERY_TERMS => 'Solarium\QueryType\Terms\Query',
self::QUERY_SPELLCHECK => 'Solarium\QueryType\Spellcheck\Query', self::QUERY_SPELLCHECK => 'Solarium\QueryType\Spellcheck\Query',
self::QUERY_SUGGESTER => 'Solarium\QueryType\Suggester\Query', self::QUERY_SUGGESTER => 'Solarium\QueryType\Suggester\Query',
self::QUERY_STREAM => 'Solarium\QueryType\Stream\Query',
self::QUERY_EXTRACT => 'Solarium\QueryType\Extract\Query', self::QUERY_EXTRACT => 'Solarium\QueryType\Extract\Query',
self::QUERY_REALTIME_GET => 'Solarium\QueryType\RealtimeGet\Query', self::QUERY_REALTIME_GET => 'Solarium\QueryType\RealtimeGet\Query',
]; ];
...@@ -1145,6 +1151,18 @@ class Client extends Configurable implements ClientInterface ...@@ -1145,6 +1151,18 @@ class Client extends Configurable implements ClientInterface
return $this->createQuery(self::QUERY_EXTRACT, $options); return $this->createQuery(self::QUERY_EXTRACT, $options);
} }
/**
* Create a stream query instance.
*
* @param mixed $options
*
* @return \Solarium\QueryType\Stream\Query
*/
public function createStream($options = null)
{
return $this->createQuery(self::QUERY_STREAM, $options);
}
/** /**
* Create a RealtimeGet query instance. * Create a RealtimeGet query instance.
* *
......
<?php
namespace Solarium\QueryType\Stream;
use Solarium\Exception\InvalidArgumentException;
/**
* Stream expression builder.
**/
class Expression
{
/**
* @param string $name
* @param array $arguments
*
* @return string
*
* @throws InvalidArgumentException
*/
public function __call(string $name, array $arguments)
{
return $name.'('.implode(', ', array_filter($arguments, function ($value) {
if (is_array($value) || (is_object($value) && !method_exists($value, '__toString'))) {
throw new InvalidArgumentException('An expression argument must be a scalar value or an object that provides a __toString() method.');
}
if (is_string($value)) {
$value = trim($value);
}
// Eliminate empty string arguments.
return '' !== $value;
})).')';
}
}
<?php
namespace Solarium\QueryType\Stream;
use Solarium\Core\Client\Client;
use Solarium\Core\Query\AbstractQuery as BaseQuery;
/**
* Stream query.
**/
class Query extends BaseQuery
{
/**
* Default options.
*
* @var array
*/
protected $options = [
'resultclass' => 'Solarium\QueryType\Stream\Result',
'handler' => 'stream',
];
/**
* Get type for this query.
*
* @return string
*/
public function getType()
{
return Client::QUERY_STREAM;
}
/**
* Get a requestbuilder for this query.
*
* @return RequestBuilder
*/
public function getRequestBuilder()
{
return new RequestBuilder();
}
/**
* The stream query has no response parser so we return a null value.
*/
public function getResponseParser()
{
}
/**
* Set the expression.
*
* @param string $expr
*
* @return self Provides fluent interface
*/
public function setExpression($expr)
{
return $this->setOption('expr', $expr);
}
/**
* Get the expression.
*
* @return string
*/
public function getExpression()
{
return $this->getOption('expr');
}
}
<?php
namespace Solarium\QueryType\Stream;
use Solarium\Core\Client\Request;
use Solarium\Core\Query\QueryInterface;
use Solarium\Core\Query\RequestBuilderInterface;
/**
* Build a stream request.
*/
class RequestBuilder implements RequestBuilderInterface
{
/**
* Build request for a stream query.
*
* @param QueryInterface|Query $query
*
* @return Request
*/
public function build(QueryInterface $query)
{
$request = new Request();
$request->setHandler($query->getHandler());
$request->addParam('expr', $query->getExpression());
$request->addParams($query->getParams());
$request->setMethod(Request::METHOD_POST);
$request->addHeader('Content-Type: text/plain; charset=utf-8');
return $request;
}
}
<?php
namespace Solarium\QueryType\Stream;
use Solarium\Core\Query\Result\Result as BaseResult;
/**
* Stream query result.
*/
class Result extends BaseResult
{
/**
* Get Solr status code.
*
* @return int
*/
public function getStatusCode()
{
return $this->response->getStatusCode();
}
/**
* Get Solr response body.
*
* @return string A JSON encoded string
*/
public function getBody()
{
return $this->response->getBody();
}
/**
* Get Solr response data.
*
* Includes a lazy loading mechanism: JSON body data is decoded on first use and then saved for reuse.
*
* @return array
*/
public function getData()
{
if (null === $this->data) {
$this->data = json_decode($this->response->getBody(), true);
}
return $this->data;
}
}
<?php
namespace Solarium\Tests\QueryType\Stream\Query;
use PHPUnit\Framework\TestCase;
use Solarium\Exception\InvalidArgumentException;
use Solarium\QueryType\Stream\Expression;
class ExpressionTest extends TestCase
{
/**
* @var Expression
*/
protected $exp;
public function setUp()
{
$this->exp = new Expression();
}
public function testExpression()
{
$expression_string = $this->exp
->search('collection', 'q=field1:"value1"', 'fq="field2:value2"', 'fl="field1, field2"', 'sort="field1 ASC, field2 ASC"', 'qt="/export"');
$this->assertSame(
'search(collection, q=field1:"value1", fq="field2:value2", fl="field1, field2", sort="field1 ASC, field2 ASC", qt="/export")',
$expression_string
);
}
public function testEmptyArgument()
{
$expression_string = $this->exp
->search('collection', 'q=field1:"value1"', '', 'fl="field1, field2"', 'sort="field1 ASC, field2 ASC"', 'qt="/export"');
$this->assertSame(
'search(collection, q=field1:"value1", fl="field1, field2", sort="field1 ASC, field2 ASC", qt="/export")',
$expression_string
);
}
public function testObject()
{
$expression_string = $this->exp
->search(new CollectionDummy(), 'q=field1:"value1"', 'fl="field1, field2"', 'sort="field1 ASC, field2 ASC"', 'qt="/export"');
$this->assertSame(
'search(dummy, q=field1:"value1", fl="field1, field2", sort="field1 ASC, field2 ASC", qt="/export")',
$expression_string
);
$exception = null;
try {
$this->exp->search(new \stdClass(), 'q=field1:"value1"', 'fl="field1, field2"', 'sort="field1 ASC, field2 ASC"', 'qt="/export"');
} catch (InvalidArgumentException $exception) {
}
$this->assertNotNull($exception);
}
public function testArray()
{
$exception = null;
try {
$this->exp->search(['array'], 'q=field1:"value1"', 'fl="field1, field2"', 'sort="field1 ASC, field2 ASC"', 'qt="/export"');
} catch (InvalidArgumentException $exception) {
}
$this->assertNotNull($exception);
}
public function testNestedExpressions()
{
$expression_string =
$this->exp->innerJoin(
$this->exp->search('collection', 'q=field1:"value1"', 'fq="field2:value2"', 'fl="field1, field2"', 'sort="field1 ASC, field2 ASC"', 'qt="/export"'),
$this->exp->search('collection', 'q=field3:"value3"', 'fl="field3, field4"', 'sort="field4 ASC"', 'qt="/export"'),
'on="field1=field2"'
);
$this->assertSame(
'innerJoin(search(collection, q=field1:"value1", fq="field2:value2", fl="field1, field2", sort="field1 ASC, field2 ASC", qt="/export"), search(collection, q=field3:"value3", fl="field3, field4", sort="field4 ASC", qt="/export"), on="field1=field2")',
$expression_string
);
}
}
class CollectionDummy
{
public function __toString()
{
return 'dummy';
}
}
<?php
namespace Solarium\Tests\QueryType\Stream\Query;
use PHPUnit\Framework\TestCase;
use Solarium\QueryType\Stream\Query;
class QueryTest extends TestCase
{
/**
* @var Query
*/
protected $query;
public function setUp()
{
$this->query = new Query();
}
public function testConfigMode()
{
$q = new Query(['expr' => 'e1']);
$this->assertSame('e1', $q->getExpression());
}
public function testSetAndGetExpression()
{
$this->query->setExpression('testexpression');
$this->assertSame('testexpression', $this->query->getExpression());
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment