Elasticsearch index gets created automatically based on the mapping you define so you don't really need to interfere it. However, you can manually create and manipulate elasticsearch index with a custom model_to_elastica_transformer service option in configuration instead. In such case, even if you defined fields in mappings option, they all will be ignored. Example depends on FOSElasticaBundle library.

In the example below, we're going to manipulate actual "price" by increasing it by 1 if the it is less than 4 otherwise decrease it by 1 for only published records and completely ignore indexing unpublished ones.


Database


mysql> SELECT * FROM post LIMIT 10;
+----+---------+-------------+---------------+------+-------+--------------+---------------------+
| id | title | description | author | year | price | is_published | created_at |
+----+---------+-------------+---------------+------+-------+--------------+---------------------+
| 1 | Desc | Cript B | Robert | 2000 | 5.55 | 1 | 2016-05-20 21:14:40 |
| 2 | Desc | Title | Andy Garcia | 2015 | 0.50 | 0 | 2016-05-20 21:15:00 |
| 3 | Eltit | Title 3 | Robert DeNiro | 2005 | 4.00 | 0 | 2016-05-20 21:15:00 |
| 4 | Eltit | Title 3 | Robert | 2015 | 3.99 | 1 | 2016-05-20 21:15:00 |
| 5 | Title 2 | Title 3 | Andy | 2000 | 4.00 | 1 | 2016-05-20 21:15:00 |
| 6 | Eltit B | Desc 1 | Andy | 2010 | 2.50 | 0 | 2016-05-20 21:15:00 |
| 7 | Title 2 | Desc 1 | Pacino | 2000 | 3.99 | 0 | 2016-05-20 21:15:00 |
| 8 | Title 1 | Desc 1 | DeNiro | 2010 | 5.55 | 1 | 2016-05-20 21:15:00 |
| 9 | Eltit A | Cript B | Andy Garcia | 2015 | 5.55 | 1 | 2016-05-20 21:15:00 |
| 10 | Eltit | Desc 2 | Pacino | 2000 | 3.99 | 0 | 2016-05-20 21:15:00 |
+----+---------+-------------+---------------+------+-------+--------------+---------------------+
10 rows in set (0.00 sec)

Elasticsearch query


curl -XPOST "http://127.0.0.1:9200/_search?post_dev" -d'
{
"query": {
"bool": {
"must": [
{
"match_all": []
}
]
}
},
"sort": [
{
"id": {
"order": "id",
"ignore_unmapped": true
}
}
],
"from": "0",
"size": "10"
}'

Example without transformer


This example should index all the records in database without a condition and show them to us as is in the query result below.


Config


fos_elastica:
clients:
default: { host: 127.0.0.1, port: 9200 }
indexes:
post_index:
client: default
index_name: post_dev
types:
post:
mappings:
id:
type: integer
title:
type: string
description:
type: string
year:
type: integer
price:
type: double
is_published:
type: boolean
created_at:
type: date
persistence:
driver: orm
model: Application\SearchBundle\Entity\Post
finder: ~
provider: ~
listener: ~

Query result


{
"took": 2,
"timed_out": false,
"_shards": {
"total": 15,
"successful": 15,
"failed": 0
},
"hits": {
"total": 1003,
"max_score": null,
"hits": [
{
"_index": "post_dev",
"_type": "post",
"_id": "1",
"_score": null,
"_source": {
"id": 1,
"title": "Desc",
"description": "Cript B",
"year": "2000",
"price": "5.55",
"is_published": true,
"created_at": "2016-05-20T21:14:40+01:00"
},
"sort": [
1
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "2",
"_score": null,
"_source": {
"id": 2,
"title": "Desc",
"description": "Title",
"year": "2015",
"price": "0.50",
"is_published": false,
"created_at": "2016-05-20T21:15:00+01:00"
},
"sort": [
2
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "3",
"_score": null,
"_source": {
"id": 3,
"title": "Eltit",
"description": "Title 3",
"year": "2005",
"price": "4.00",
"is_published": false,
"created_at": "2016-05-20T21:15:00+01:00"
},
"sort": [
3
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "4",
"_score": null,
"_source": {
"id": 4,
"title": "Eltit",
"description": "Title 3",
"year": "2015",
"price": "3.99",
"is_published": true,
"created_at": "2016-05-20T21:15:00+01:00"
},
"sort": [
4
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "5",
"_score": null,
"_source": {
"id": 5,
"title": "Title 2",
"description": "Title 3",
"year": "2000",
"price": "4.00",
"is_published": true,
"created_at": "2016-05-20T21:15:00+01:00"
},
"sort": [
5
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "6",
"_score": null,
"_source": {
"id": 6,
"title": "Eltit B",
"description": "Desc 1",
"year": "2010",
"price": "2.50",
"is_published": false,
"created_at": "2016-05-20T21:15:00+01:00"
},
"sort": [
6
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "7",
"_score": null,
"_source": {
"id": 7,
"title": "Title 2",
"description": "Desc 1",
"year": "2000",
"price": "3.99",
"is_published": false,
"created_at": "2016-05-20T21:15:00+01:00"
},
"sort": [
7
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "8",
"_score": null,
"_source": {
"id": 8,
"title": "Title 1",
"description": "Desc 1",
"year": "2010",
"price": "5.55",
"is_published": true,
"created_at": "2016-05-20T21:15:00+01:00"
},
"sort": [
8
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "9",
"_score": null,
"_source": {
"id": 9,
"title": "Eltit A",
"description": "Cript B",
"year": "2015",
"price": "5.55",
"is_published": true,
"created_at": "2016-05-20T21:15:00+01:00"
},
"sort": [
9
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "10",
"_score": null,
"_source": {
"id": 10,
"title": "Eltit",
"description": "Desc 2",
"year": "2000",
"price": "3.99",
"is_published": false,
"created_at": "2016-05-20T21:15:00+01:00"
},
"sort": [
10
]
}
]
}
}

Example with transformer


This example should index only published records in database, set only specific fields as we want, manipulate some values and show them to us in the query result below. Even if you add mappings options below, they all will be ignored so no point of adding them.


Config


fos_elastica:
clients:
default: { host: 127.0.0.1, port: 9200 }
indexes:
post_index:
client: default
index_name: post_dev
types:
post:
mappings: ~
persistence:
driver: orm
model: Application\SearchBundle\Entity\Post
finder: ~
provider: ~
listener: ~
model_to_elastica_transformer:
service: application_search.service.post_to_elastica_transformer

Transformer class


The line $data['null'] = null; will not create any record in elasticsearch index.


namespace Application\SearchBundle\Service;

use Application\SearchBundle\Entity\Post;
use DateTime;
use Elastica\Document;
use FOS\ElasticaBundle\Transformer\ModelToElasticaTransformerInterface;

class PostToElasticaTransformer implements ModelToElasticaTransformerInterface
{
const PRICE_CAP = 4;
const INCREASE_BY = 1;
const DECREASE_BY = 1;

/**
* @param Post $post
* @param array $fields
*
* @return Document
*/
public function transform($post, array $fields)
{
return new Document($post->getId(), $this->getData($post));
}

private function getData(Post $post)
{
$data = [];

if (!$post->getIsPublished()) {
$data['null'] = null;
} else {
$data['id'] = $post->getId();
$data['title'] = $post->getTitle();
$data['author'] = $post->getAuthor();
$data['year'] = (int)$post->getYear();
$data['price'] = (double)$post->getPrice();
$data['sale_price'] = $this->getSalePrice($post->getPrice());
$data['sale_price_created_at'] = (new DateTime())->format(DateTime::ISO8601);
}

return $data;
}

private function getSalePrice($price)
{
return $price < self::PRICE_CAP ? $price+self::INCREASE_BY : $price-self::DECREASE_BY;
}
}

Services.yml


services:
application_search.util.post_to_elastica_transformer:
class: Application\SearchBundle\Util\PostToElasticaTransformer

Query result


As you can see below, unpublished records are ignored and new fields are added to index.


{
"took": 4,
"timed_out": false,
"_shards": {
"total": 15,
"successful": 15,
"failed": 0
},
"hits": {
"total": 1003,
"max_score": null,
"hits": [
{
"_index": "post_dev",
"_type": "post",
"_id": "1",
"_score": null,
"_source": {
"id": 1,
"title": "Desc",
"author": "Robert",
"year": 2000,
"price": 5.55,
"sale_price": 4.55,
"sale_price_created_at": "2016-05-21T21:17:58+0100"
},
"sort": [
1
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "4",
"_score": null,
"_source": {
"id": 4,
"title": "Eltit",
"author": "Robert",
"year": 2015,
"price": 3.99,
"sale_price": 4.99,
"sale_price_created_at": "2016-05-21T21:17:58+0100"
},
"sort": [
4
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "5",
"_score": null,
"_source": {
"id": 5,
"title": "Title 2",
"author": "Andy",
"year": 2000,
"price": 4,
"sale_price": 3,
"sale_price_created_at": "2016-05-21T21:17:58+0100"
},
"sort": [
5
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "8",
"_score": null,
"_source": {
"id": 8,
"title": "Title 1",
"author": "DeNiro",
"year": 2010,
"price": 5.55,
"sale_price": 4.55,
"sale_price_created_at": "2016-05-21T21:17:58+0100"
},
"sort": [
8
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "9",
"_score": null,
"_source": {
"id": 9,
"title": "Eltit A",
"author": "Andy Garcia",
"year": 2015,
"price": 5.55,
"sale_price": 4.55,
"sale_price_created_at": "2016-05-21T21:17:58+0100"
},
"sort": [
9
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "13",
"_score": null,
"_source": {
"id": 13,
"title": "Eltit",
"author": "Pacino",
"year": 2000,
"price": 0.5,
"sale_price": 1.5,
"sale_price_created_at": "2016-05-21T21:17:58+0100"
},
"sort": [
13
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "14",
"_score": null,
"_source": {
"id": 14,
"title": "Title 2",
"author": "Robert DeNiro",
"year": 2000,
"price": 0.5,
"sale_price": 1.5,
"sale_price_created_at": "2016-05-21T21:17:58+0100"
},
"sort": [
14
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "15",
"_score": null,
"_source": {
"id": 15,
"title": "Title 3",
"author": "Al",
"year": 2010,
"price": 2.5,
"sale_price": 3.5,
"sale_price_created_at": "2016-05-21T21:17:58+0100"
},
"sort": [
15
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "17",
"_score": null,
"_source": {
"id": 17,
"title": "Title 2",
"author": "Al",
"year": 2005,
"price": 5.55,
"sale_price": 4.55,
"sale_price_created_at": "2016-05-21T21:17:58+0100"
},
"sort": [
17
]
},
{
"_index": "post_dev",
"_type": "post",
"_id": "18",
"_score": null,
"_source": {
"id": 18,
"title": "Eltit",
"author": "Al",
"year": 2000,
"price": 4,
"sale_price": 3,
"sale_price_created_at": "2016-05-21T21:17:58+0100"
},
"sort": [
18
]
}
]
}
}