I have a Symfony2 project, and I'm trying to implement a search feature using Elasticsearch.
My problem is, I need to index an entity with an optional self-relation. It means that my Item entity has a "parent" field, referencing another Item.
In order to make the search, I want to create filters on that "parent" field. Is my Item.parent is NULL ? for instance.
So, I am using the FosElasticaBundle.
Here is my mapping :
types:
Item:
mappings:
name:
children:
type: object
_parent:
type: Item
parent:
type: object
_routing:
required: false
_parent:
type : Item
identifier: id
property : parent
persistence:
...
model_to_elastica_transformer:
service: core.transformer.item
And the transformer does :
$document = new Document();
if (!is_null($item->getParent())) {
$document->setParent($item->getParent()->getId());
} else {
$document->setParent(null);
}
return $document;
And, the problem occurs when I try to create my index ( php app/console fos:elastica:populate
)
This command returns the following ResponseException:
index: /traveler/Item caused RoutingMissingException[routing is required for [traveler]/[Item]/[null]]
Do you have any idea why this isn't working ? And is this the good way to do it ?
Thanks,
Since my needs are pretty simple in this case, we managed to solve this problem.
Configuration
Instead of using the _parent
field in config, I used a nested property.
Item:
mappings:
children:
type: "nested"
properties:
name: ~
parent:
type: "object"
This is a tree, so children and parent properties are both Item. I needed to create requess with filter on the parent value (is null, is equals something...)
Request
So, I used the \Elasitca\Filter\Nested.
For instance, when I need to exclude some resultats based on children's user and language, I can do the following :
$nestedFilter = new Nested();
$boolFilter = new Bool();
$boolAndFilter = new BoolAnd();
$boolAndFilter
->setFilters(array(
new Term(array("children.user.id" => $this->getClient()->getId())),
new Term(array("children.other" => $language))
))
;
$nestedFilter
->setFilter($boolAndFilter)
->setPath('children')
;
$query = new Filtered(
$query,
new BoolNot($boolFilter->addMust($nestedFilter))
);
I think this solution has limitation (for multi-level parenting I assume), but for this need, it works.