2011-12-13 11:30:45 +01:00
|
|
|
[Elastica](https://github.com/ruflin/Elastica) integration in Symfony2
|
2011-04-08 23:11:46 +02:00
|
|
|
|
|
|
|
## Installation
|
|
|
|
|
|
|
|
### Install elasticsearch
|
|
|
|
|
|
|
|
http://www.elasticsearch.org/guide/reference/setup/installation.html
|
|
|
|
|
|
|
|
### Install Elastica
|
|
|
|
|
|
|
|
#### Download
|
|
|
|
|
2011-12-13 11:49:00 +01:00
|
|
|
**With submodule**
|
2011-04-22 05:45:26 +02:00
|
|
|
|
2011-12-13 11:49:00 +01:00
|
|
|
`git submodule add git://github.com/ruflin/Elastica vendor/elastica`
|
|
|
|
|
|
|
|
**With clone**
|
|
|
|
|
|
|
|
`git clone git://github.com/ruflin/Elastica vendor/elastica`
|
|
|
|
|
|
|
|
**Using the vendors script**
|
|
|
|
|
|
|
|
Add the following lines to your deps file:
|
|
|
|
|
|
|
|
[Elastica]
|
|
|
|
git=git://github.com/ruflin/Elastica.git
|
|
|
|
target=elastica
|
2011-04-08 23:11:46 +02:00
|
|
|
|
|
|
|
#### Register autoloading
|
|
|
|
|
|
|
|
// app/autoload.php
|
|
|
|
|
|
|
|
$loader->registerPrefixes(array(
|
|
|
|
...
|
2011-04-10 23:08:51 +02:00
|
|
|
'Elastica' => __DIR__.'/../vendor/elastica/lib',
|
2011-04-08 23:11:46 +02:00
|
|
|
));
|
|
|
|
|
|
|
|
### Install ElasticaBundle
|
|
|
|
|
2011-12-13 11:30:45 +01:00
|
|
|
Use the master branch with Symfony2 master only, use the 2.0 branch with Symfony2.0.x releases.
|
|
|
|
|
2011-04-08 23:11:46 +02:00
|
|
|
#### Download
|
|
|
|
|
2011-12-13 11:49:00 +01:00
|
|
|
**With submodule**
|
|
|
|
|
|
|
|
`git submodule add git://github.com/Exercise/FOQElasticaBundle vendor/bundles/FOQ/ElasticaBundle`
|
|
|
|
|
|
|
|
**With clone**
|
|
|
|
|
|
|
|
`git clone git://github.com/Exercise/FOQElasticaBundle vendor/bundles/FOQ/ElasticaBundle`
|
|
|
|
|
|
|
|
**With the vendors script**
|
|
|
|
|
|
|
|
Add the following lines to your deps file:
|
|
|
|
|
|
|
|
[FOQElasticaBundle]
|
|
|
|
git=git://github.com/Exercise/FOQElasticaBundle.git
|
|
|
|
target=bundles/FOQ/ElasticaBundle
|
|
|
|
|
|
|
|
For the 2.0 branch for use with Symfony2.0.x releases add the following:
|
|
|
|
|
|
|
|
[FOQElasticaBundle]
|
|
|
|
git=git://github.com/Exercise/FOQElasticaBundle.git
|
|
|
|
target=bundles/FOQ/ElasticaBundle
|
|
|
|
version=origin/2.0
|
2011-04-08 23:11:46 +02:00
|
|
|
|
2011-12-13 11:49:00 +01:00
|
|
|
Run the vendors script:
|
2011-04-08 23:11:46 +02:00
|
|
|
|
2011-12-13 11:49:00 +01:00
|
|
|
```bash
|
|
|
|
$ php bin/vendors install
|
|
|
|
```
|
2011-04-08 23:11:46 +02:00
|
|
|
#### Register autoloading
|
|
|
|
|
|
|
|
// app/autoload.php
|
|
|
|
|
|
|
|
$loader->registerNamespaces(array(
|
|
|
|
...
|
2011-12-19 13:39:20 +01:00
|
|
|
'FOQ' => __DIR__.'/../vendor/bundles',
|
2011-04-08 23:11:46 +02:00
|
|
|
));
|
|
|
|
|
|
|
|
#### Register the bundle
|
|
|
|
|
|
|
|
// app/AppKernel.php
|
|
|
|
|
|
|
|
public function registerBundles()
|
|
|
|
{
|
|
|
|
return array(
|
|
|
|
// ...
|
|
|
|
new FOQ\ElasticaBundle\FOQElasticaBundle(),
|
|
|
|
// ...
|
|
|
|
);
|
|
|
|
}
|
2011-04-22 04:34:57 +02:00
|
|
|
|
|
|
|
### Basic configuration
|
|
|
|
|
2011-09-12 18:34:05 +02:00
|
|
|
#### Declare a client
|
2011-04-22 04:34:57 +02:00
|
|
|
|
2011-12-22 00:05:24 +01:00
|
|
|
Elasticsearch client is comparable to a database connection.
|
2011-04-22 04:34:57 +02:00
|
|
|
Most of the time, you will need only one.
|
|
|
|
|
|
|
|
#app/config/config.yml
|
|
|
|
foq_elastica:
|
|
|
|
clients:
|
|
|
|
default: { host: localhost, port: 9200 }
|
|
|
|
|
|
|
|
#### Declare an index
|
|
|
|
|
2011-12-22 00:05:24 +01:00
|
|
|
Elasticsearch index is comparable to Doctrine entity manager.
|
2011-04-22 04:34:57 +02:00
|
|
|
Most of the time, you will need only one.
|
|
|
|
|
|
|
|
foq_elastica:
|
|
|
|
clients:
|
|
|
|
default: { host: localhost, port: 9200 }
|
|
|
|
indexes:
|
|
|
|
website:
|
|
|
|
client: default
|
|
|
|
|
|
|
|
Here we created a "website" index, that uses our "default" client.
|
|
|
|
|
2011-04-22 19:16:31 +02:00
|
|
|
Our index is now available as a service: `foq_elastica.index.website`. It is an instance of `Elastica_Index`.
|
2011-04-22 05:45:26 +02:00
|
|
|
|
2011-04-22 04:34:57 +02:00
|
|
|
#### Declare a type
|
|
|
|
|
2011-12-22 00:05:24 +01:00
|
|
|
Elasticsearch type is comparable to Doctrine entity repository.
|
2011-04-22 04:34:57 +02:00
|
|
|
|
|
|
|
foq_elastica:
|
|
|
|
clients:
|
|
|
|
default: { host: localhost, port: 9200 }
|
|
|
|
indexes:
|
|
|
|
website:
|
|
|
|
client: default
|
|
|
|
types:
|
|
|
|
user:
|
|
|
|
mappings:
|
|
|
|
username: { boost: 5 }
|
|
|
|
firstName: { boost: 3 }
|
|
|
|
lastName: { boost: 3 }
|
2011-09-12 18:34:05 +02:00
|
|
|
aboutMe:
|
2011-04-22 04:34:57 +02:00
|
|
|
|
2011-04-22 19:16:31 +02:00
|
|
|
Our type is now available as a service: `foq_elastica.index.website.user`. It is an instance of `Elastica_Type`.
|
2011-04-22 05:45:26 +02:00
|
|
|
|
2011-04-22 04:34:57 +02:00
|
|
|
### Populate the types
|
|
|
|
|
|
|
|
php app/console foq:elastica:populate
|
|
|
|
|
2011-04-22 19:16:31 +02:00
|
|
|
This command deletes and creates the declared indexes and types.
|
2011-04-22 05:45:26 +02:00
|
|
|
It applies the configured mappings to the types.
|
|
|
|
|
2011-04-22 04:34:57 +02:00
|
|
|
This command needs providers to insert new documents in the elasticsearch types.
|
|
|
|
There are 2 ways to create providers.
|
2011-12-22 00:05:24 +01:00
|
|
|
If your elasticsearch type matches a Doctrine repository or a Propel query, go for the persistence automatic provider.
|
2011-04-22 05:45:26 +02:00
|
|
|
Or, for complete flexibility, go for manual provider.
|
2011-04-22 04:34:57 +02:00
|
|
|
|
2011-12-22 00:05:24 +01:00
|
|
|
#### Persistence automatic provider
|
2011-04-22 04:34:57 +02:00
|
|
|
|
2011-12-22 00:05:24 +01:00
|
|
|
If we want to index the entities from a Doctrine repository or a Propel query,
|
2011-04-22 19:16:31 +02:00
|
|
|
some configuration will let ElasticaBundle do it for us.
|
2011-04-22 04:34:57 +02:00
|
|
|
|
|
|
|
foq_elastica:
|
|
|
|
clients:
|
|
|
|
default: { host: localhost, port: 9200 }
|
|
|
|
indexes:
|
|
|
|
website:
|
|
|
|
client: default
|
|
|
|
types:
|
|
|
|
user:
|
|
|
|
mappings:
|
2011-06-07 20:13:34 +02:00
|
|
|
username: { boost: 5 }
|
|
|
|
firstName: { boost: 3 }
|
|
|
|
# more mappings...
|
2011-12-22 00:05:24 +01:00
|
|
|
persistence:
|
|
|
|
driver: orm # orm, mongodb, propel are available
|
2011-05-09 05:22:51 +02:00
|
|
|
model: Application\UserBundle\Entity\User
|
|
|
|
provider:
|
2011-04-22 04:34:57 +02:00
|
|
|
|
2011-12-22 00:05:24 +01:00
|
|
|
Three drivers are actually supported: orm, mongodb, and propel.
|
2011-04-22 04:34:57 +02:00
|
|
|
|
2011-12-22 00:05:24 +01:00
|
|
|
##### Use a custom Doctrine query builder
|
2011-04-22 04:34:57 +02:00
|
|
|
|
2011-04-22 05:45:26 +02:00
|
|
|
You can control which entities will be indexed by specifying a custom query builder method.
|
2011-04-22 04:34:57 +02:00
|
|
|
|
2011-12-22 00:05:24 +01:00
|
|
|
persistence:
|
2011-05-09 05:22:51 +02:00
|
|
|
driver: orm
|
|
|
|
model: Application\UserBundle\Entity\User
|
|
|
|
provider:
|
|
|
|
query_builder_method: createIsActiveQueryBuilder
|
2011-04-22 04:34:57 +02:00
|
|
|
|
2011-12-22 00:05:24 +01:00
|
|
|
Your repository must implement this method and return a Doctrine query builder.
|
|
|
|
|
|
|
|
> **Propel** doesn't support this feature yet.
|
2011-04-22 05:45:26 +02:00
|
|
|
|
|
|
|
##### Change the batch size
|
|
|
|
|
|
|
|
By default, ElasticaBundle will index documents by paquets of 100.
|
|
|
|
You can change this value in the provider configuration.
|
|
|
|
|
2011-12-22 00:05:24 +01:00
|
|
|
persistence:
|
2011-05-09 05:22:51 +02:00
|
|
|
driver: orm
|
|
|
|
model: Application\UserBundle\Entity\User
|
|
|
|
provider:
|
|
|
|
batch_size: 100
|
2011-04-22 05:45:26 +02:00
|
|
|
|
|
|
|
##### Change the document identifier field
|
|
|
|
|
|
|
|
By default, ElasticaBundle will use the `id` field of your entities as the elasticsearch document identifier.
|
2012-03-13 18:42:27 +01:00
|
|
|
You can change this value in the persistence configuration.
|
2011-04-22 05:45:26 +02:00
|
|
|
|
2011-12-22 00:05:24 +01:00
|
|
|
persistence:
|
2011-05-09 05:22:51 +02:00
|
|
|
driver: orm
|
|
|
|
model: Application\UserBundle\Entity\User
|
2012-03-13 18:42:27 +01:00
|
|
|
identifier: id
|
2011-04-22 05:45:26 +02:00
|
|
|
|
|
|
|
#### Manual provider
|
|
|
|
|
2012-03-13 18:44:49 +01:00
|
|
|
Create a service with the tag "foq_elastica.provider" and attributes for the
|
|
|
|
index and type for which the service will provide.
|
2011-04-22 05:45:26 +02:00
|
|
|
|
|
|
|
<service id="acme.search_provider.user" class="Acme\UserBundle\Search\UserProvider">
|
2012-03-13 18:44:49 +01:00
|
|
|
<tag name="foq_elastica.provider" index="website" type="user" />
|
2011-04-22 05:45:26 +02:00
|
|
|
<argument type="service" id="foq_elastica.index.website.user" />
|
|
|
|
</service>
|
|
|
|
|
|
|
|
Its class must implement `FOQ\ElasticaBundle\Provider\ProviderInterface`.
|
|
|
|
|
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Acme\UserBundle\Provider;
|
|
|
|
|
|
|
|
use FOQ\ElasticaBundle\Provider\ProviderInterface;
|
|
|
|
use Elastica_Type;
|
|
|
|
|
|
|
|
class UserProvider implements ProviderInterface
|
|
|
|
{
|
|
|
|
protected $userType;
|
|
|
|
|
|
|
|
public function __construct(Elastica_Type $userType)
|
|
|
|
{
|
|
|
|
$this->userType = $userType;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Insert the repository objects in the type index
|
|
|
|
*
|
|
|
|
* @param Closure $loggerClosure
|
|
|
|
*/
|
2012-03-13 18:44:49 +01:00
|
|
|
public function populate(Closure $loggerClosure = null)
|
2011-04-22 05:45:26 +02:00
|
|
|
{
|
2012-03-13 18:44:49 +01:00
|
|
|
if ($loggerClosure) {
|
|
|
|
$loggerClosure('Indexing users');
|
|
|
|
}
|
2011-04-22 05:45:26 +02:00
|
|
|
|
|
|
|
$this->userType->addDocuments(array(
|
|
|
|
array('username' => 'Bob')
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-25 14:46:15 +01:00
|
|
|
You will find a more complete implementation example in `src/FOQ/ElasticaBundle/Doctrine/AbstractProvider.php`.
|
2011-04-22 05:45:26 +02:00
|
|
|
|
|
|
|
### Search
|
|
|
|
|
|
|
|
You can just use the index and type Elastica objects, provided as services, to perform searches.
|
|
|
|
|
|
|
|
/** var Elastica_Type */
|
|
|
|
$userType = $this->container->get('foq_elastica.index.website.user');
|
|
|
|
|
|
|
|
/** var Elastica_ResultSet */
|
|
|
|
$resultSet = $userType->search('bob');
|
|
|
|
|
2012-01-25 14:46:15 +01:00
|
|
|
#### Doctrine/Propel finder
|
2011-04-22 05:45:26 +02:00
|
|
|
|
2011-12-22 00:05:24 +01:00
|
|
|
If your elasticsearch type is bound to a Doctrine entity repository or a Propel query,
|
2011-04-22 05:45:26 +02:00
|
|
|
you can get your entities instead of Elastica results when you perform a search.
|
2011-12-22 00:05:24 +01:00
|
|
|
Declare that you want a Doctrine/Propel finder in your configuration:
|
2011-04-22 05:45:26 +02:00
|
|
|
|
|
|
|
foq_elastica:
|
|
|
|
clients:
|
|
|
|
default: { host: localhost, port: 9200 }
|
|
|
|
indexes:
|
|
|
|
website:
|
|
|
|
client: default
|
|
|
|
types:
|
|
|
|
user:
|
|
|
|
mappings:
|
|
|
|
# your mappings
|
2011-12-22 00:05:24 +01:00
|
|
|
persistence:
|
2011-05-09 05:22:51 +02:00
|
|
|
driver: orm
|
|
|
|
model: Application\UserBundle\Entity\User
|
|
|
|
provider:
|
|
|
|
finder:
|
2011-04-22 05:45:26 +02:00
|
|
|
|
|
|
|
You can now use the `foq_elastica.finder.website.user` service:
|
|
|
|
|
|
|
|
/** var FOQ\ElasticaBundle\Finder\MappedFinder */
|
2011-05-15 03:56:48 +02:00
|
|
|
$finder = $container->get('foq_elastica.finder.website.user');
|
2011-04-22 05:45:26 +02:00
|
|
|
|
|
|
|
/** var array of Acme\UserBundle\Entity\User */
|
|
|
|
$users = $finder->find('bob');
|
|
|
|
|
2011-05-15 03:56:48 +02:00
|
|
|
/** var array of Acme\UserBundle\Entity\User limited to 10 results */
|
|
|
|
$users = $finder->find('bob', 10);
|
|
|
|
|
2011-04-22 05:45:26 +02:00
|
|
|
You can even get paginated results!
|
|
|
|
|
2012-06-13 18:40:41 +02:00
|
|
|
Pagerfanta:
|
|
|
|
|
2011-07-05 19:42:14 +02:00
|
|
|
/** var Pagerfanta\Pagerfanta */
|
2011-04-22 05:45:26 +02:00
|
|
|
$userPaginator = $finder->findPaginated('bob');
|
2011-06-07 20:13:34 +02:00
|
|
|
|
2012-06-13 18:40:41 +02:00
|
|
|
Knp paginator:
|
|
|
|
|
|
|
|
$paginator = $this->get('knp_paginator');
|
|
|
|
$userPaginator = $paginator->paginate($finder->createPaginatorAdapter('bob'));
|
|
|
|
|
2012-01-03 23:16:56 +01:00
|
|
|
##### Index wide finder
|
|
|
|
|
|
|
|
You can also define a finder that will work on the entire index. Adjust your index
|
|
|
|
configuration as per below:
|
|
|
|
|
|
|
|
foq_elastica:
|
|
|
|
indexes:
|
|
|
|
website:
|
|
|
|
client: default
|
|
|
|
finder:
|
|
|
|
|
|
|
|
You can now use the index wide finder service `foq_elastica.finder.website`:
|
|
|
|
|
|
|
|
/** var FOQ\ElasticaBundle\Finder\MappedFinder */
|
|
|
|
$finder = $container->get('foq_elastica.finder.website');
|
|
|
|
|
|
|
|
// Returns a mixed array of any objects mapped
|
|
|
|
$results = $finder->find('bob');
|
|
|
|
|
2012-01-25 14:46:15 +01:00
|
|
|
#### Repositories
|
|
|
|
|
|
|
|
As well as using the finder service for a particular Doctrine/Propel entity you
|
|
|
|
can use a manager service for each driver and get a repository for an entity to search
|
|
|
|
against. This allows you to use the same service rather than the particular finder. For
|
|
|
|
example:
|
|
|
|
|
|
|
|
/** var FOQ\ElasticaBundle\Manager\RepositoryManager */
|
|
|
|
$repositoryManager = $container->get('foq_elastica.manager.orm');
|
|
|
|
|
|
|
|
/** var FOQ\ElasticaBundle\Repository */
|
|
|
|
$repository = $repositoryManager->getRepository('UserBundle:User');
|
|
|
|
|
|
|
|
/** var array of Acme\UserBundle\Entity\User */
|
|
|
|
$users = $finder->find('bob');
|
|
|
|
|
|
|
|
You can also specify the full name of the entity instead of the shortcut syntax:
|
|
|
|
|
|
|
|
/** var FOQ\ElasticaBundle\Repository */
|
|
|
|
$repository = $repositoryManager->getRepository('Application\UserBundle\Entity\User');
|
|
|
|
|
|
|
|
> The **2.0** branch doesn't support using `UserBundle:User` style syntax and you must use the full name of the entity. .
|
|
|
|
|
|
|
|
##### Default Manager
|
|
|
|
|
|
|
|
If you are only using one driver then its manager service is automatically aliased
|
|
|
|
to `foq_elastica.manager`. So the above example could be simplified to:
|
|
|
|
|
|
|
|
/** var FOQ\ElasticaBundle\Manager\RepositoryManager */
|
|
|
|
$repositoryManager = $container->get('foq_elastica.manager');
|
|
|
|
|
|
|
|
/** var FOQ\ElasticaBundle\Repository */
|
|
|
|
$repository = $repositoryManager->getRepository('UserBundle:User');
|
|
|
|
|
|
|
|
/** var array of Acme\UserBundle\Entity\User */
|
|
|
|
$users = $finder->find('bob');
|
|
|
|
|
|
|
|
If you use multiple drivers then you can choose which one is aliased to `foq_elastica.manager`
|
|
|
|
using the `default_manager` parameter:
|
|
|
|
|
|
|
|
foq_elastica:
|
|
|
|
default_manager: mongodb #defauults to orm
|
|
|
|
clients:
|
|
|
|
default: { host: localhost, port: 9200 }
|
|
|
|
#--
|
|
|
|
|
|
|
|
##### Custom Repositories
|
|
|
|
|
|
|
|
As well as the default repository you can create a custom repository for an entity and add
|
|
|
|
methods for particular searches. These need to extend `FOQ\ElasticaBundle\Repository` to have
|
|
|
|
access to the finder:
|
|
|
|
|
|
|
|
```
|
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Acme\ElasticaBundle\SearchRepository;
|
|
|
|
|
|
|
|
use FOQ\ElasticaBundle\Repository;
|
|
|
|
|
|
|
|
class UserRepository extends Repository
|
|
|
|
{
|
|
|
|
public function findWithCustomQuery($searchText)
|
|
|
|
{
|
|
|
|
// build $query with Elastica objects
|
|
|
|
$this->find($query);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
To use the custom repository specify it in the mapping for the entity:
|
|
|
|
|
2012-01-25 15:15:20 +01:00
|
|
|
foq_elastica:
|
2012-01-25 14:46:15 +01:00
|
|
|
clients:
|
|
|
|
default: { host: localhost, port: 9200 }
|
|
|
|
indexes:
|
|
|
|
website:
|
|
|
|
client: default
|
|
|
|
types:
|
|
|
|
user:
|
|
|
|
mappings:
|
|
|
|
# your mappings
|
|
|
|
persistence:
|
|
|
|
driver: orm
|
|
|
|
model: Application\UserBundle\Entity\User
|
|
|
|
provider:
|
|
|
|
finder:
|
|
|
|
repository: Acme\ElasticaBundle\SearchRepository\UserRepository
|
|
|
|
|
|
|
|
Then the custom queries will be available when using the repository returned from the manager:
|
|
|
|
|
|
|
|
/** var FOQ\ElasticaBundle\Manager\RepositoryManager */
|
|
|
|
$repositoryManager = $container->get('foq_elastica.manager');
|
|
|
|
|
|
|
|
/** var FOQ\ElasticaBundle\Repository */
|
|
|
|
$repository = $repositoryManager->getRepository('UserBundle:User');
|
|
|
|
|
|
|
|
/** var array of Acme\UserBundle\Entity\User */
|
|
|
|
$users = $finder->findWithCustomQuery('bob');
|
|
|
|
|
|
|
|
Alternatively you can specify the custom repository using an annotation in the entity:
|
|
|
|
|
|
|
|
```
|
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Application\UserBundle\Entity;
|
|
|
|
|
|
|
|
use FOQ\ElasticaBundle\Configuration\Search;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @Search(repositoryClass="Acme\ElasticaBundle\SearchRepository\UserRepository")
|
|
|
|
*/
|
|
|
|
class User
|
|
|
|
{
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2011-06-07 20:13:34 +02:00
|
|
|
### Realtime, selective index update
|
|
|
|
|
2011-12-22 00:05:24 +01:00
|
|
|
If you use the Doctrine integration, you can let ElasticaBundle update the indexes automatically
|
|
|
|
when an object is added, updated or removed. It uses Doctrine lifecycle events.
|
2011-06-07 20:13:34 +02:00
|
|
|
Declare that you want to update the index in real time:
|
|
|
|
|
|
|
|
foq_elastica:
|
|
|
|
clients:
|
|
|
|
default: { host: localhost, port: 9200 }
|
|
|
|
indexes:
|
|
|
|
website:
|
|
|
|
client: default
|
|
|
|
types:
|
|
|
|
user:
|
|
|
|
mappings:
|
|
|
|
# your mappings
|
2011-12-22 00:05:24 +01:00
|
|
|
persistence:
|
2011-06-07 20:13:34 +02:00
|
|
|
driver: orm
|
|
|
|
model: Application\UserBundle\Entity\User
|
|
|
|
listener: # by default, listens to "insert", "update" and "delete"
|
|
|
|
|
2011-12-22 00:05:24 +01:00
|
|
|
Now the index is automatically updated each time the state of the bound Doctrine repository changes.
|
2011-06-07 20:13:34 +02:00
|
|
|
No need to repopulate the whole "user" index when a new `User` is created.
|
|
|
|
|
|
|
|
You can also choose to only listen for some of the events:
|
|
|
|
|
2011-12-22 00:05:24 +01:00
|
|
|
persistence:
|
2011-06-07 20:13:34 +02:00
|
|
|
listener:
|
|
|
|
insert: true
|
|
|
|
update: false
|
|
|
|
delete: true
|
2011-09-12 18:34:05 +02:00
|
|
|
|
2011-12-22 00:05:24 +01:00
|
|
|
> **Propel** doesn't support this feature yet.
|
|
|
|
|
2012-04-05 15:15:08 +02:00
|
|
|
### Checking an entity method for listener
|
|
|
|
|
2012-04-16 18:45:10 +02:00
|
|
|
If you use listeners to update your index, you may need to validate your
|
|
|
|
entities before you index them (e.g. only index "public" entities). Typically,
|
|
|
|
you'll want the listener to be consistent with the provider's query criteria.
|
|
|
|
This may be achieved by using the `is_indexable_callback` config parameter:
|
2012-04-05 15:15:08 +02:00
|
|
|
|
|
|
|
persistence:
|
|
|
|
listener:
|
2012-04-16 18:45:10 +02:00
|
|
|
is_indexable_callback: "isPublic"
|
2012-04-05 15:15:08 +02:00
|
|
|
|
2012-04-16 18:45:10 +02:00
|
|
|
If `is_indexable_callback` is a string and the entity has a method with the
|
|
|
|
specified name, the listener will only index entities for which the method
|
|
|
|
returns `true`. Additionally, you may provide a service and method name pair:
|
|
|
|
|
|
|
|
persistence:
|
|
|
|
listener:
|
|
|
|
is_indexable_callback: [ "%custom_service_id%", "isIndexable" ]
|
|
|
|
|
|
|
|
In this case, the callback will be the `isIndexable()` method on the specified
|
2012-04-17 18:43:18 +02:00
|
|
|
service and the object being considered for indexing will be passed as the only
|
|
|
|
argument. This allows you to do more complex validation (e.g. ACL checks).
|
2012-04-16 18:45:10 +02:00
|
|
|
|
|
|
|
As you might expect, new entities will only be indexed if the callback returns
|
|
|
|
`true`. Additionally, modified entities will be updated or removed from the
|
|
|
|
index depending on whether the callback returns `true` or `false`, respectively.
|
|
|
|
The delete listener disregards the callback.
|
2012-04-05 15:15:08 +02:00
|
|
|
|
|
|
|
> **Propel** doesn't support this feature yet.
|
|
|
|
|
2011-09-12 18:34:05 +02:00
|
|
|
### Advanced elasticsearch configuration
|
|
|
|
|
|
|
|
Any setting can be specified when declaring a type. For example, to enable a custom analyzer, you could write:
|
|
|
|
|
|
|
|
foq_elastica:
|
|
|
|
indexes:
|
|
|
|
doc:
|
2011-12-19 13:39:20 +01:00
|
|
|
settings:
|
|
|
|
index:
|
|
|
|
analysis:
|
|
|
|
analyzer:
|
|
|
|
my_analyzer:
|
2011-09-12 18:34:05 +02:00
|
|
|
type: custom
|
|
|
|
tokenizer: lowercase
|
|
|
|
filter : [my_ngram]
|
2011-12-19 13:39:20 +01:00
|
|
|
filter:
|
|
|
|
my_ngram:
|
2011-09-12 18:34:05 +02:00
|
|
|
type: "nGram"
|
|
|
|
min_gram: 3
|
|
|
|
max_gram: 5
|
|
|
|
types:
|
|
|
|
blog:
|
|
|
|
mappings:
|
|
|
|
title: { boost: 8, analyzer: my_analyzer }
|
2011-12-28 23:08:47 +01:00
|
|
|
|
|
|
|
### Overriding the Client class to suppress exceptions
|
|
|
|
|
2012-01-25 14:46:15 +01:00
|
|
|
By default, exceptions from the Elastica client library will propagate through
|
2011-12-28 23:08:47 +01:00
|
|
|
the bundle's Client class. For instance, if the elasticsearch server is offline,
|
|
|
|
issuing a request will result in an `Elastica_Exception_Client` being thrown.
|
|
|
|
Depending on your needs, it may be desirable to suppress these exceptions and
|
|
|
|
allow searches to fail silently.
|
|
|
|
|
|
|
|
One way to achieve this is to override the `foq_elastica.client.class` service
|
|
|
|
container parameter with a custom class. In the following example, we override
|
|
|
|
the `Client::request()` method and return the equivalent of an empty search
|
|
|
|
response if an exception occurred.
|
|
|
|
|
|
|
|
```
|
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Acme\ElasticaBundle;
|
|
|
|
|
|
|
|
use FOQ\ElasticaBundle\Client as BaseClient;
|
|
|
|
|
|
|
|
class Client extends BaseClient
|
|
|
|
{
|
|
|
|
public function request($path, $method, $data = array())
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
return parent::request($path, $method, $data);
|
|
|
|
} catch (\Elastica_Exception_Abstract $e) {
|
|
|
|
return new \Elastica_Response('{"took":0,"timed_out":false,"hits":{"total":0,"max_score":0,"hits":[]}}');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|