21/05/2016 - ELASTICSEARCH, SYMFONY
Hazırladığımız mapping bilgilerine göre elasticsearch index otomatik olarak yaratılır, bu nedenle çok fazla birşey yapmamız gerekmez. Ama eğer indexi kendiniz manuel olarak yaratmak veya manipüle etmek isterseniz, model_to_elastica_transformer
servis seçeneğini kullanabilirsiniz. Bu gibi durumlarda mappings
bilgilerini tanımlasanız bile, bunların hepsi index yaratılırken göz ardı edilir. Örneğimiz FOSElasticaBundle kullanıyor.
Aşağıdaki örneğimizde, "price" alanını manipüle edeceğiz. Değeri 4'den az olanları 1 yükseltip, diğerlerini de 1 azaltacağız. Bu sadece "published" alanı "true" olan kayılar için geçerlidir ve "false" olanlar hiçbir şekilde indexlenmeyecektir.
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)
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"
}'
Bu örnek veritabanındaki kayıları olduğu gibi indexleyecek ve sonuçları bize olduğu gibi verecektir.
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: ~
{
"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
]
}
]
}
}
Bu örnekte sadece "published" alanı "true" olan kayıtlar indexlenecek, belirlenen alanlar seçilecek, bazı veriler değiştirilecek ve sorgu sonucunda bize sonuç olarak gösterilecekler. Eğer mappings
bilgilerini tanımlasanız bile, bunların hepsi index yaratılırken göz ardı edilecektir.
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
Aşağıdaki $data['null'] = null;
satırı, elasticsearch index içinede kayıt yaratmayı engellemek için kullanılır.
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:
application_search.util.post_to_elastica_transformer:
class: Application\SearchBundle\Util\PostToElasticaTransformer
Aşağıda da gördüğümüz gibi, sadece "published" alanı "true" olan kayıtlar indexlenmiş ve birtakım yeni alanlar eklenmiş durumda.
{
"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
]
}
]
}
}