2011-04-08 23:11:46 +02:00
|
|
|
[Elastica](https://github.com/ruflin/Elastica) integration in Symfony2
|
|
|
|
|
|
|
|
## Installation
|
|
|
|
|
|
|
|
### Install elasticsearch
|
|
|
|
|
|
|
|
http://www.elasticsearch.org/guide/reference/setup/installation.html
|
|
|
|
|
|
|
|
### Install Elastica
|
|
|
|
|
|
|
|
#### Download
|
|
|
|
|
2011-04-22 19:16:31 +02:00
|
|
|
With submodule: `git submodule add git://github.com/ruflin/Elastica vendor/elastica`
|
2011-04-22 05:45:26 +02:00
|
|
|
|
2011-04-22 19:16:31 +02:00
|
|
|
With clone: `git clone git://github.com/ruflin/Elastica vendor/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
|
|
|
|
|
|
|
|
#### Download
|
|
|
|
|
2011-07-20 11:17:32 +02:00
|
|
|
With submodule: `git submodule add git://github.com/Exercise/FOQElasticaBundle src/FOQ/ElasticaBundle`
|
2011-04-08 23:11:46 +02:00
|
|
|
|
2011-07-20 11:17:32 +02:00
|
|
|
With clone: `git clone git://github.com/Exercise/FOQElasticaBundle src/FOQ/ElasticaBundle`
|
2011-04-08 23:11:46 +02:00
|
|
|
|
|
|
|
#### Register autoloading
|
|
|
|
|
|
|
|
// app/autoload.php
|
|
|
|
|
|
|
|
$loader->registerNamespaces(array(
|
|
|
|
...
|
|
|
|
'FOQ' => __DIR__.'/../src',
|
|
|
|
));
|
|
|
|
|
|
|
|
#### 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
|
|
|
|
|
|
|
|
#### Declare a client
|
|
|
|
|
|
|
|
Elasticsearch client is comparable to doctrine connection.
|
|
|
|
Most of the time, you will need only one.
|
|
|
|
|
|
|
|
#app/config/config.yml
|
|
|
|
foq_elastica:
|
|
|
|
clients:
|
|
|
|
default: { host: localhost, port: 9200 }
|
|
|
|
|
|
|
|
#### Declare an index
|
|
|
|
|
|
|
|
Elasticsearch index is comparable to doctrine entity manager.
|
|
|
|
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
|
|
|
|
|
|
|
|
Elasticsearch type is comparable to doctrine entity repository.
|
|
|
|
|
|
|
|
foq_elastica:
|
|
|
|
clients:
|
|
|
|
default: { host: localhost, port: 9200 }
|
|
|
|
indexes:
|
|
|
|
website:
|
|
|
|
client: default
|
|
|
|
types:
|
|
|
|
user:
|
|
|
|
mappings:
|
|
|
|
username: { boost: 5 }
|
|
|
|
firstName: { boost: 3 }
|
|
|
|
lastName: { boost: 3 }
|
|
|
|
aboutMe:
|
|
|
|
|
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.
|
|
|
|
If your elasticsearch type matches a doctrine repository, go for the doctrine 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
|
|
|
|
|
|
|
#### Doctrine automatic provider
|
|
|
|
|
|
|
|
If we want to index the entities from a doctrine repository,
|
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-05-09 05:22:51 +02:00
|
|
|
doctrine:
|
|
|
|
driver: orm
|
|
|
|
model: Application\UserBundle\Entity\User
|
|
|
|
provider:
|
2011-04-22 04:34:57 +02:00
|
|
|
|
|
|
|
Two drivers are actually supported: orm and mongodb.
|
|
|
|
|
|
|
|
##### Use a custom doctrine query builder
|
|
|
|
|
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-05-09 05:22:51 +02:00
|
|
|
doctrine:
|
|
|
|
driver: orm
|
|
|
|
model: Application\UserBundle\Entity\User
|
|
|
|
provider:
|
|
|
|
query_builder_method: createIsActiveQueryBuilder
|
2011-04-22 04:34:57 +02:00
|
|
|
|
|
|
|
Your repository must implement this method and return a doctrine query builder.
|
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-05-09 05:22:51 +02:00
|
|
|
doctrine:
|
|
|
|
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.
|
|
|
|
You can change this value in the provider configuration.
|
|
|
|
|
2011-05-09 05:22:51 +02:00
|
|
|
doctrine:
|
|
|
|
driver: orm
|
|
|
|
model: Application\UserBundle\Entity\User
|
|
|
|
provider:
|
|
|
|
identifier: id
|
2011-04-22 05:45:26 +02:00
|
|
|
|
|
|
|
#### Manual provider
|
|
|
|
|
|
|
|
Create a service with the tag "foq_elastica.provider".
|
|
|
|
|
|
|
|
<service id="acme.search_provider.user" class="Acme\UserBundle\Search\UserProvider">
|
|
|
|
<tag name="foq_elastica.provider" />
|
|
|
|
<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
|
|
|
|
*/
|
|
|
|
public function populate(Closure $loggerClosure)
|
|
|
|
{
|
|
|
|
$loggerClosure('Indexing users');
|
|
|
|
|
|
|
|
$this->userType->addDocuments(array(
|
|
|
|
array('username' => 'Bob')
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
You will find a more complete implementation example in src/FOQ/ElasticaBundle/Provider/DoctrineProvider.php
|
|
|
|
|
|
|
|
### 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');
|
|
|
|
|
|
|
|
#### Doctrine finder
|
|
|
|
|
|
|
|
If your elasticsearch type is bound to a doctrine entity repository,
|
|
|
|
you can get your entities instead of Elastica results when you perform a search.
|
|
|
|
Declare that you want a doctrine finder in your configuration:
|
|
|
|
|
|
|
|
foq_elastica:
|
|
|
|
clients:
|
|
|
|
default: { host: localhost, port: 9200 }
|
|
|
|
indexes:
|
|
|
|
website:
|
|
|
|
client: default
|
|
|
|
types:
|
|
|
|
user:
|
|
|
|
mappings:
|
|
|
|
# your mappings
|
2011-05-09 05:22:51 +02:00
|
|
|
doctrine:
|
|
|
|
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!
|
|
|
|
|
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
|
|
|
|
|
|
|
### Realtime, selective index update
|
|
|
|
|
|
|
|
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.
|
|
|
|
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
|
|
|
|
doctrine:
|
|
|
|
driver: orm
|
|
|
|
model: Application\UserBundle\Entity\User
|
|
|
|
listener: # by default, listens to "insert", "update" and "delete"
|
|
|
|
|
|
|
|
Now the index is automatically updated each time the state of the bound doctrine repository changes.
|
|
|
|
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:
|
|
|
|
|
|
|
|
doctrine:
|
|
|
|
listener:
|
|
|
|
insert: true
|
|
|
|
update: false
|
|
|
|
delete: true
|