Commit fa383609 authored by Markus Kalkbrenner's avatar Markus Kalkbrenner Committed by GitHub

Improved streaming expression result and added graph query for GraphML (#582)

Improved streaming expression result and added graph query for GraphML
parent 853b566e
......@@ -92,6 +92,11 @@ class Client extends Configurable implements ClientInterface
*/
const QUERY_STREAM = 'stream';
/**
* Querytype graph.
*/
const QUERY_GRAPH = 'graph';
/**
* Querytype extract.
*/
......@@ -130,6 +135,7 @@ class Client extends Configurable implements ClientInterface
self::QUERY_SPELLCHECK => 'Solarium\QueryType\Spellcheck\Query',
self::QUERY_SUGGESTER => 'Solarium\QueryType\Suggester\Query',
self::QUERY_STREAM => 'Solarium\QueryType\Stream\Query',
self::QUERY_GRAPH => 'Solarium\QueryType\Graph\Query',
self::QUERY_EXTRACT => 'Solarium\QueryType\Extract\Query',
self::QUERY_REALTIME_GET => 'Solarium\QueryType\RealtimeGet\Query',
];
......@@ -1163,6 +1169,18 @@ class Client extends Configurable implements ClientInterface
return $this->createQuery(self::QUERY_STREAM, $options);
}
/**
* Create a graph query instance.
*
* @param mixed $options
*
* @return \Solarium\QueryType\Graph\Query
*/
public function createGraph($options = null)
{
return $this->createQuery(self::QUERY_GRAPH, $options);
}
/**
* Create a RealtimeGet query instance.
*
......
<?php
namespace Solarium\Exception;
/**
* StreamException exception for Solarium classes.
*/
class StreamException extends \UnexpectedValueException implements ExceptionInterface
{
}
<?php
namespace Solarium\QueryType\Graph;
use Solarium\Core\Client\Client;
use Solarium\Core\Query\AbstractQuery;
use Solarium\QueryType\Stream\RequestBuilder;
/**
* Graph query.
*/
class Query extends AbstractQuery
{
/**
* Default options.
*
* @var array
*/
protected $options = [
'handler' => 'graph',
'resultclass' => 'Solarium\QueryType\Graph\Result',
];
/**
* Get type for this query.
*
* @return string
*/
public function getType()
{
return Client::QUERY_GRAPH;
}
/**
* Get a requestbuilder for this query.
*
* @return RequestBuilder
*/
public function getRequestBuilder()
{
return new RequestBuilder();
}
/**
* No response parser required since we pass through GraphML.
*/
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\Graph;
use Solarium\Core\Query\Result\Result as BaseResult;
/**
* Graph 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 The response body
*/
public function getData()
{
return $this->response->getBody();
}
/**
* Get Solr response data in GraphML format.
*
* More expressive convenience method that just call getData().
*
* @return string GraphML XML document
*/
public function getGraphML()
{
return $this->getData();
}
}
......@@ -261,30 +261,6 @@ class Query extends AbstractQuery implements ComponentAwareQueryInterface
return $this->getOption('start');
}
/**
* Set a custom resultclass.
*
* @param string $value classname
*
* @return self Provides fluent interface
*/
public function setResultClass($value)
{
return $this->setOption('resultclass', $value);
}
/**
* Get the current resultclass option.
*
* The value is a classname, not an instance
*
* @return string
*/
public function getResultClass()
{
return $this->getOption('resultclass');
}
/**
* Set a custom document class.
*
......
......@@ -15,7 +15,6 @@ class ResponseParser extends ResponseParserAbstract implements ResponseParserInt
/**
* Get result data for the response.
*
*
* @param Result $result
*
* @throws RuntimeException
......
......@@ -3,12 +3,12 @@
namespace Solarium\QueryType\Stream;
use Solarium\Core\Client\Client;
use Solarium\Core\Query\AbstractQuery as BaseQuery;
use Solarium\Core\Query\AbstractQuery;
/**
* Stream query.
**/
class Query extends BaseQuery
*/
class Query extends AbstractQuery
{
/**
* Default options.
......@@ -16,8 +16,9 @@ class Query extends BaseQuery
* @var array
*/
protected $options = [
'resultclass' => 'Solarium\QueryType\Stream\Result',
'handler' => 'stream',
'resultclass' => 'Solarium\QueryType\Stream\Result',
'documentclass' => 'Solarium\QueryType\Select\Result\Document',
];
/**
......@@ -41,10 +42,13 @@ class Query extends BaseQuery
}
/**
* The stream query has no response parser so we return a null value.
* Get a response parser for this query.
*
* @return ResponseParser
*/
public function getResponseParser()
{
return new ResponseParser();
}
/**
......@@ -68,4 +72,30 @@ class Query extends BaseQuery
{
return $this->getOption('expr');
}
/**
* Set a custom document class.
*
* This class should implement the document interface
*
* @param string $value classname
*
* @return self Provides fluent interface
*/
public function setDocumentClass($value)
{
return $this->setOption('documentclass', $value);
}
/**
* Get the current documentclass option.
*
* The value is a classname, not an instance
*
* @return string
*/
public function getDocumentClass()
{
return $this->getOption('documentclass');
}
}
<?php
namespace Solarium\QueryType\Stream;
use Solarium\Core\Query\AbstractResponseParser as ResponseParserAbstract;
use Solarium\Core\Query\ResponseParserInterface as ResponseParserInterface;
use Solarium\Exception\RuntimeException;
use Solarium\Exception\StreamException;
use Solarium\QueryType\Select\Result\Result;
/**
* Parse streaming expression response data.
*/
class ResponseParser extends ResponseParserAbstract implements ResponseParserInterface
{
/**
* Get result data for the response.
*
* @param Result $result
*
* @throws RuntimeException
*
* @return array
*/
public function parse($result)
{
$data = $result->getData();
/*
* @var Query
*/
$query = $result->getQuery();
// create document instances
$documentClass = $query->getOption('documentclass');
$classes = class_implements($documentClass);
if (!in_array('Solarium\QueryType\Select\Result\DocumentInterface', $classes, true)) {
throw new RuntimeException('The result document class must implement a document interface');
}
$documents = [];
if (isset($data['result-set']['docs'])) {
foreach ($data['result-set']['docs'] as $doc) {
$fields = (array) $doc;
if (isset($fields['EXCEPTION'])) {
// Use Solr's exception as message.
throw new StreamException($fields['EXCEPTION']);
}
if (isset($fields['EOF'])) {
// End of stream.
break;
}
$documents[] = new $documentClass($fields);
}
if (!isset($fields['EOF'])) {
throw new StreamException('Streaming expression returned an incomplete result-set.');
}
$data['responseHeader']['QTime'] = $fields['RESPONSE_TIME'];
$data['responseHeader']['status'] = 0;
} else {
throw new StreamException('Streaming expression did not return a result-set.');
}
return $this->addHeaderInfo(
$data,
[
'documents' => $documents,
]
);
}
}
......@@ -2,13 +2,52 @@
namespace Solarium\QueryType\Stream;
use Solarium\Core\Query\Result\Result as BaseResult;
use Solarium\Core\Query\Result\QueryType as BaseResult;
use Solarium\QueryType\Select\Result\DocumentInterface;
/**
* Stream query result.
*/
class Result extends BaseResult
class Result extends BaseResult implements \IteratorAggregate, \Countable
{
/**
* Document instances array.
*
* @var array
*/
protected $documents;
/**
* Status code returned by Solr.
*
* @var int
*/
protected $status;
/**
* Solr index queryTime.
*
* This doesn't include things like the HTTP responsetime. Purely the Solr
* query execution time.
*
* @var int
*/
protected $queryTime;
/**
* Get Solr status code.
*
* This is not the HTTP status code! The normal value for success is 0.
*
* @return int
*/
public function getStatus()
{
$this->parseResponse();
return $this->status;
}
/**
* Get Solr status code.
*
......@@ -19,6 +58,42 @@ class Result extends BaseResult
return $this->response->getStatusCode();
}
/**
* Get all documents.
*
* @return DocumentInterface[]
*/
public function getDocuments()
{
$this->parseResponse();
return $this->documents;
}
/**
* IteratorAggregate implementation.
*
* @return \ArrayIterator
*/
public function getIterator()
{
$this->parseResponse();
return new \ArrayIterator($this->documents);
}
/**
* Countable implementation.
*
* @return int
*/
public function count()
{
$this->parseResponse();
return count($this->documents);
}
/**
* Get Solr response body.
*
......
<?php
namespace Solarium\Tests\QueryType\Graph\Query;
use PHPUnit\Framework\TestCase;
use Solarium\QueryType\Graph\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