Skip to content

Commit

Permalink
implementation and documentation
Browse files Browse the repository at this point in the history
- added query builder implementation in query trait
- added query builder implementation for adding filter queries
- added some documentation for the query builder
  • Loading branch information
wickedOne committed Jul 14, 2020
1 parent a87dc71 commit d65cd8e
Show file tree
Hide file tree
Showing 10 changed files with 313 additions and 56 deletions.
84 changes: 84 additions & 0 deletions docs/queries/query-helper/query-builder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
Query builder
-------------

The query builder is a simple helper class to help writing and maintaining (filter) queries using Solr's query language.
While the query will only accept a single (composite) expression, the addition of filter queries can consist of multiple expressions.

Query example
-------------
```php
<?php

use Solarium\Builder\Select\QueryBuilder;

// ...

$query = $client->createSelect();

$expr = QueryBuilder::expr();
$builder = QueryBuilder::create()
->where($expr->andX(
$expr->eq('foo', 'bar'),
$expr->eq('baz', 'qux')
))
;

$query->setQueryFromQueryBuilder($builder);

// which would be equal to
$query->setQuery('foo:"bar" AND baz:"qux"');
```

Filter Query example
-------------
```php
<?php

use Solarium\Builder\Select\QueryBuilder;

// ...

$query = $client->createSelect();

$expr = QueryBuilder::expr();
$builder = QueryBuilder::create()
->where($expr->eq('foo', 'bar')),
->andWhere($expr->neq('baz', 'qux')
);

$query->addFilterQueriesFromQueryBuilder($builder);

// which would be equal to
$value = 'foo:"bar"';
$query->addFilterQuery(['key' => sha1($value), 'query' => $value]);
$value = '-baz:"qux"';
$query->addFilterQuery(['key' => sha1($value), 'query' => $value]);
```

Complex filter queries
----------------------
While the ``addFilterQueriesFromQueryBuilder`` method only provides in setting the facet query key and actual query, the ``QueryBuilder`` can be used in the construction of more complex facet queries.
If one, for example, need to add a tag to the filter query the following method could be used.
```php
<?php

use Solarium\Builder\Select\QueryBuilder;
use Solarium\Builder\Select\QueryExpressionVisitor;

// ...

$query = $client->createSelect();

$expr = QueryBuilder::expr();
$visitor = new QueryExpressionVisitor();

$builder = QueryBuilder::create()
->where($expr->eq('foo', 'bar'))
);

$query->addFilterQuery([
'key' => 'my-key,
'query' => $visitor->dispatch($builder->getExpression()[0]),
'local_tag' => 'my-tag',
]);
```
5 changes: 5 additions & 0 deletions src/Builder/Comparison.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ class Comparison implements ExpressionInterface
*/
public const MATCH = 'MATCH';

/**
* Empty.
*/
public const EMPTY = 'EMPTY';

/**
* @var string
*/
Expand Down
10 changes: 10 additions & 0 deletions src/Builder/Select/ExpressionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,14 @@ public function match(string $field, $value): Comparison
{
return new Comparison($field, Comparison::MATCH, $value);
}

/**
* @param string $field
*
* @return \Solarium\Builder\Comparison
*/
public function empty(string $field): Comparison
{
return new Comparison($field, Comparison::EMPTY, null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*
* @author wicliff <wicliff.wolda@gmail.com>
*/
class FilterBuilder
class QueryBuilder
{
/**
* @var \Solarium\Builder\ExpressionInterface[]
Expand Down
2 changes: 2 additions & 0 deletions src/Builder/Select/QueryExpressionVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ public function walkExpression(ExpressionInterface $expression)
}

return sprintf('%s:%s', $field, $this->valueToString($value, ',', '', false));
case Comparison::EMPTY:
return sprintf('(*:* NOT %s:*)', $field);
default:
throw new RuntimeException('Unknown comparison operator: '.$expression->getOperator());
}
Expand Down
20 changes: 20 additions & 0 deletions src/Component/QueryTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

namespace Solarium\Component;

use Solarium\Builder\Select\QueryBuilder;
use Solarium\Builder\Select\QueryExpressionVisitor;
use Solarium\Exception\RuntimeException;

/**
* Query Trait.
*/
Expand All @@ -27,6 +31,22 @@ public function setQuery(string $query, array $bind = null): QueryInterface
return $this->setOption('query', trim($query));
}

/**
* @param \Solarium\Builder\Select\QueryBuilder $builder
*
* @return \Solarium\Component\QueryInterface
*
* @throws \Solarium\Exception\RuntimeException
*/
public function setQueryFromQueryBuilder(QueryBuilder $builder): QueryInterface
{
if (1 !== count($builder->getExpressions())) {
throw new RuntimeException('The QueryBuilder can only contain one expression when setting the query. Use ExpressionBuilder::andX or ExpressionBuilder::orX to combine expressions.');
}

return $this->setOption('query', (new QueryExpressionVisitor())->dispatch($builder->getExpressions()[0]));
}

/**
* Get query option.
*
Expand Down
24 changes: 24 additions & 0 deletions src/QueryType/Select/Query/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Solarium\QueryType\Select\Query;

use Solarium\Builder\Select\QueryBuilder;
use Solarium\Builder\Select\QueryExpressionVisitor;
use Solarium\Component\Analytics\Analytics;
use Solarium\Component\ComponentAwareQueryInterface;
use Solarium\Component\ComponentAwareQueryTrait;
Expand Down Expand Up @@ -581,6 +583,28 @@ public function addFilterQueries(array $filterQueries): self
return $this;
}

/**
* Add multiple filter queries from the QueryBuilder.
*
* @param \Solarium\Builder\Select\QueryBuilder $builder
*
* @return $this
*
* @throws \Solarium\Exception\RuntimeException
*/
public function addFilterQueriesFromQueryBuilder(QueryBuilder $builder): self
{
$visitor = new QueryExpressionVisitor();

foreach ($builder->getExpressions() as $expression) {
$value = $visitor->dispatch($expression);

$this->addFilterQuery(new FilterQuery(['key' => sha1($value), 'query' => $value]));
}

return $this;
}

/**
* Get a filterquery.
*
Expand Down
Loading

0 comments on commit d65cd8e

Please sign in to comment.