Dynamic Aggregate Filter
Here we provide a full example of how to implement dynamic aggregate filter.
1. Create a document
We will create a Product
document with a nested attributes
object that the
filter will be applied on.
// src/AppBundle/Document/Product.php
namespace AppBundle\Document;
use ONGR\ElasticsearchBundle\Annotation as ES;
use ONGR\ElasticsearchBundle\Collection\Collection;
/**
* @ES\Document(type="product")
*/
class Product
{
/**
* @var string
*
* @ES\Id()
*/
public $id;
/**
* @ES\Property(type="keyword")
*/
public $title;
/**
* @var Attribute[]
* @ES\Embedded(class="AppBundle:Attribute", multiple=true)
*/
public $attributes;
public function __construct()
{
$this->attributes = new Collection();
}
}
And now the Attribute
object class:
// src/AppBundle/Document/Attribute.php
namespace AppBundle\Document;
use ONGR\ElasticsearchBundle\Annotation as ES;
/**
* @ES\Nested()
*/
class Attribute
{
/**
* @var string
* @ES\Property(type="keyword", options={"index":"not_analyzed"})
*/
public $name;
/**
* @var string
* @ES\Property(type="keyword", options={"index":"not_analyzed"})
*/
public $value;
}
Note that internally
DynamicAggregateFilter
uses theTermQuery
, which means that if the index will be analyzed you may get unexpected results with it or it may not work at all. If you need the properties analyzed for other search operations, you can use multi field annotations
3. Adding filter to manager
Adding filter to the manager is a standard procedure as with all the filters:
# app/config/config.yml
ongr_filter_manager:
managers:
attribute_list:
filters:
- attributes
repository: 'es.manager.default.product'
filters:
attributes:
type: dynamic_aggregate
request_field: 'attributes'
document_field: attributes>attributes.value
options:
name_field: attributes.name
4. Using filter
As with any other filter, in order to use it, the request needs to be handled in the controller:
/**
* Main action for lists
*
* @param Request $request
*
* @return Response
*/
public function listAction(Request $request)
{
$filterManager = $this->get('ongr_filter_manager.attribute_list')->handleRequest($request);
return $this->render('default/list.html.twig', [
'filter_manager' => $filterManager,
]);
}
The resulting documents will be filtered depending on the request and the formation of the available choices can be made like this:
<ul>
{% for choices in filter_manager.getFilters().getItems() %}
<li>
<a href="#"><strong>{{ choices.name }}</strong></a>
</li>
{% for choice in choices.choices %}
<li>
{% if choice.active %}
<a href="{{ path(active_category, choice.getUrlParameters()) }}"
class="list-group-item active">{{ choice.label }}({{ choice.count }})</a>
{% else %}
<a href="{{ path(active_category, choice.getUrlParameters()) }}"
class="list-group-item">{{ choice.label }} ({{ choice.count }})</a>
{% endif %}
</li>
{% endfor %}
{% endfor %}
</ul>