50
Novidades do Elasticsearch 2.0 e como usá-lo com PHP Luiz Henrique Zambom Santana https://github.com/lhzsantana Meetup - PHPSC 13 de Fevereiro de 2016 Florianópolis/SC

Novidades do elasticsearch 2.0 e como usá-lo com PHP

Embed Size (px)

Citation preview

Novidades do Elasticsearch 2.0 e como usá-lo com PHP

Luiz Henrique Zambom Santanahttps://github.com/lhzsantana

Meetup - PHPSC13 de Fevereiro de 2016

Florianópolis/SC

Agenda

Visão geral

Arquitetura de soluções

Desenvolvimento com o Elasticsearch

Elasticsearch com PHP

Novas possibilidades

Conclusões

• Doutorando na UFSC• Consultor e programador• Trabalhando com Elasticsearch desde 2013 (versão 0.9.x)• Autor de artigos, Blog (luizsantana.info) e livros

Apresentação

Not only SQLSadalage e Fowler, 2012(http://martinfowler.com/books/nosql.html)

Relational databases will be a footnote in history

Nathan Marz, 2014 (http://www.slideshare.net/nathanmarz/runaway-complexity-in-big-data-and-a-plan-to-stop-it)

Visão geral

Visão geral - Por que busca e analytics?

Visão geral - Por que em tempo real?

Visão geral - Elasticsearch buzz

Visão geral - Por que Elasticsearch?• Tempo real• Flexível• Livre de esquema e muito escalável

• Iniciado por Shay Banon em 2010• Desenvolvido pela comunidade• Código aberto em:

• https://github.com/elastic/elasticsearch• Atualmente apoiado pela Elastic

Visão geral - Onde é usado?

Mais casos de uso em: https://www.elastic.co/use-cases

Visão geral

• Cluster• Lucene• Índice• Mapeamento• Tipo Lucene Banco de dados relacional (BDR)

Índice (Index) Esquema

Type TabelaDocumento (JSON) Linha

Campo (Field) ColunaMapeamento (Mapping) Estrutura da tabela

Query DSL SQL

Arquitetura - Indexação

Client API ElasticsearchUsuários

Usuários

Arquitetura - Busca

Client API ElasticsearchUsuários

Usuários

Arquitetura - Autocomplete (“search as you type”)

Client API ElasticsearchUsuários

Usuários

Arquitetura - Indexação em lote

ElasticsearchAPI

Desenvolvimento com o Elasticsearch - Pontos importantes

Gerenciamento dos dados

Backup do Elasticsearch?

Geralmente o Elasticsearch é usado como um repositório volátil

Backup:

https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html

Segurança:

https://www.elastic.co/products/shield

Mapeamento

Desenvolvimento com o Elasticsearch - Instalação

•Simplesmente baixar e desempacotar•Elasticsearch

•https://www.elastic.co/downloads/elasticsearch•Versão 2.2.0

•Iniciar:•/bin/elasticsearch

•Em produção não é tão simples:•http://logz.io/blog/deploy-elk-production/

Verificar se está funcionando (localhost:9200)

Sense

Criar índice e mapeamento no Elasticsearch• Exemplo simples “Post” e “Comentário” para o site do PHPSC

• Criar um índice seria tão simples como:• PUT phpsc

• O mapeamento no Elasticsearch é flat• O Elasticsearch está configurado para buscar palavras em Inglês

• Usar um analisador para português• GIST:

• https://gist.github.com/lhzsantana/4f940684075ce115d799• ES 2.0

• Os campos multifields (como o author) devem ser definidos com a palavra “fields” no lugar de “properties”

• Ao contrário do ES 1.* em uma relação parent/child o filho deve ser criado antes do pai

Indexar alguns documentosPOST phpsc/post/1{ "author":"Luiz", "text":"Tá muito sol para falar de Elasticsearch", "hashtag":"#queriatánapraia"}

POST phpsc/post{ "author":"Luiz", "text":"Esse post não tem ID", "hashtag":"#seráqfunciona"}

Indexar alguns documentosPOST phpsc/post/1{ "author":"Luiz", "text":"Elasticsearch é mais legal que praia", "hashtag":"#sqn"}

POST phpsc/post{ "author":"Luiz", "text":"O mapeamento do Elasticsearch é flexível", "local":"Florianópolis", "hashtag":"#schemaless"}

Indexar alguns documentos

POST phpsc/comments/1{ "author":"Anônimo", "text": "Até agora não vi nada de PHP", "hashtag":"#taenrolando"}

POST phpsc/comment/1?parent=1{ "author":"Anônimo", "text": "Jurerê ou PHP?", "hashtag":"#queriatánapraia"}

Indexar alguns documentos

• ES 2.0• Os nomes de campos não podem conter ponto (.)• O documento não pode estar “dentro” do seu type

• Os campos devem ser referenciados por seu nome completo. Antes poderíamos acessar o campo “raw” diretamente, agora sempre devemos acessar “author.raw”

PUT my_index/my_type/1{ "my_type": { "text": "quick brown fox" }}

PUT my_index/my_type/1{ "text": "quick brown fox"}

Como ficou o mapeamento?

• GET phpsc/_mapping• Mapping com o nome errado “comments”• O campo “local” não tem analisador

https://gist.github.com/lhzsantana/b72dd13f339ff29b4682

BuscaGET /_search{ "query": { "match_all": {} }}

GET /phpsc/_search{ "query": { "match_all": {} }}

GET /phpsc/post/_search{ "query": { "match_all": {} }}

GET /phpsc/post,comment/_search{ "query": { "match_all": {} }}

GET /phpsc,phpsp/_search{ "query": { "match_all": {} }}

GET /phpsc,phpsp/post,comment/_search{ "query": { "match_all": {} }}

BuscaGET /_search{ "query": { "match": { "author": "luiz" } }}

BuscaGET /_search{ "query": { "match": { "local": "florianopolis" } }}

Busca - bool, boost e agregaçõesGET /phpsc/post,comment/_search{ "sort": [ { "author": { "order": "desc" } } ], "size": 100,

"query": { "bool": { "should": [{ "match": { "author": "anônimo" }}, { "match": { "local": "Florianópolis" } } ] } ,

"aggs" : { "hashtags" : { "terms" : { "field" : "author.raw" } } }

https://gist.github.com/lhzsantana/f552751d66a153741657

Busca - bool, boost e agregações

{ "took": 88, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 },

"hits": { "total": 2, "max_score": null, "hits": [{ "_index": "phpsc", "_type": "post", "_id": "AVLauzKDtyulCxogNOoi", "_score": null, "_source": { "author": "Luiz", "text": "O mapeamento do Elasticsearch é flexível",

"local": "Florianópolis", "hashtag": "#schemaless" },

"aggregations": {

"hashtags": {

"doc_count_error_upper_bound": 0,

"sum_other_doc_count": 0,

"buckets": [

{

"key": "anônimo",

"doc_count": 1

},

{

"key": "luiz",

"doc_count": 1

}

]

}

}

}

Primeiro de tudo:

https://www.elastic.co/guide/en/elasticsearch/client/php-api/2.0/index.html

{ "require": { "elasticsearch/elasticsearch": "~2.0@beta" }}

Em geral, a criação de índices e mapeamentos é uma atividade de DEVOPS

Existem receitas de ansible para Elasticsearch

https://github.com/Traackr/ansible-elasticsearch

Mas… poderia ser criado com PHP

https://www.elastic.co/guide/en/elasticsearch/client/php-api/2.0/_index_management_operations.html

Elasticsearch com PHP

Elasticsearch com PHP - Criar o cliente

$hosts = [ '192.168.1.1:9200', // IP + Port '192.168.1.2', // Just IP 'mydomain.server.com:9201', // Domain + Port 'mydomain2.server.com', // Just Domain 'https://localhost', // SSL to localhost 'https://192.168.1.3:9200' // SSL to IP + Port];

$client = ClientBuilder::create() // Instantiate a new ClientBuilder ->setHosts($hosts) // Set the hosts ->build(); // Build the client object

Num cluster, todos IPs devem estar entre os hosts. O cliente irá acessar em round-

robin.

Elasticsearch com PHP - Indexação

$params = [ 'index' => phpsc, 'type' => 'post', 'body' =>

[ 'author' => 'Luiz','text' => 'Ufaaa finalmente PHP :)'

]];

$response = $client->index($params);

Elasticsearch com PHP - Recuperar com ID

$params = [ 'index' => 'phpsc', 'type' => 'post', 'id' => '1'];

$response = $client->get($params);

Elasticsearch com PHP - Buscar

$params = [ 'index' => phpsc, 'type' => 'post', 'body' => [ 'query' => [ 'match' => [ 'author' => 'Luiz' ] ] ]];

$results = $client->search($params);

//resultados

$milliseconds = $results['took'];$maxScore = $results['hits']['max_score'];

$score = $results['hits']['hits'][0]['_score'];$docs = $results['hits']['hits'];

Elasticsearch com PHP - Filtros já não existem no ES 2.0!

$params = [ 'index' => phpsc, 'type' => 'post', 'body' => [ 'query' => [ 'match' => [ 'author' => 'Luiz' ] ], 'filter' => [ 'match' => [ 'local' => 'Florianópolis' ] ] ]];

$results = $client->search($params);

USE QUERY

Elasticsearch com PHP - Boolean

$params = [ 'index' => 'phpsc', 'type' => 'post', 'body' => [ 'query' => [ 'bool' => [ 'should' => [ [ 'match' => [ 'author' => 'luiz' ] ], [ 'match' => [ 'local' => 'florianópolis' ] ], ] ] ] ]];$results = $client->search($params);

Elasticsearch com PHP - Desafio

$params = [ 'index' => 'phpsc', 'type' => 'post',//sort 'body' => [ 'query' => [ ],

//aggregations ]];$results = $client->search($params);

Elasticsearch com PHP - Pontos importantesEvite fazer múltiplas chamadas para o cluster, principalmente em “search as you

type”

Desafio 2

Como fazer multi-index e multi-type em PHP?

Elasticsearch com PHP - Pontos importantesMSearch

$params = [ 'index' => 'phpsc', 'body' => [ ['type' => 'post'], ['query' => ['match_all' => []]], ['type' => 'comment'], ['query' => ['match_all' => []]] ]];

$results = $client->msearch($params);

//resultados$responses = $results['responses']['hits']['hits'];

$posts = $responses[0]['hits']['hits'];$comments = $responses[1]['hits']['hits'];

Elasticsearch com PHPBulk no lugar de Rivers para o ES 2.0!

if (!is_string($type) || !is_string($operation)) { throw new InvalidArgumentException();}$response = [];

if (!empty($json)) { $params = []; for ($i = 0; $i < count($json); $i++) { $params['body'][] = [ 'index' => $index, 'type' => $type ];

$params['body'][] = [ $json [$i] ];}

$response = $this->elasticsearchClient->bulk($params);

{ "index" : { "_index" : "test", "_type" : "type1", "_id" : "1" } }{ "field1" : "value1" }{ "delete" : { "_index" : "test", "_type" : "type1", "_id" : "2" } }{ "create" : { "_index" : "test", "_type" : "type1", "_id" : "3" } }{ "field1" : "value3" }{ "update" : {"_id" : "1", "_type" : "type1", "_index" : "index1"} }{ "doc" : {"field2" : "value2"} }

$ curl -s -XPOST localhost:9200/_bulk --data-binary "@requests"; echo{"took":7,"items":[{"create":{"_index":"test","_type":"type1","_id":"1","_version":1}}]}

Elasticsearch com PHP - Suggestionparams = [ 'hashtag-suggest' => [ "text" => “#qu”, "completion" => [ "field" => "hashtags.suggest" ] ]];

$response = $this->client->suggest(params);

//resultados if (!isset($response['hashtag-suggest'])) { return ['items' => []]; }

$items = [];

foreach ($response['hashtag-suggest'] as $item) { foreach ($item['options'] as $option) { $items[] = $option['text']; } }

return ['items' => $items];

Elasticsearch com PHP - Outros endpoints

$results = $client->delete($params);

$results = $client->update($params);

...

Elasticsearch com PHP - Array x JSON

$json = '{ "query" : { "match" : { "author" : "Luiz" } }}';

$params = [ 'index' => 'phpsc', 'type' => 'post', 'body' => $json];

$results = $client->search($params);

$params = [ 'index' =>'phpsc', 'type' => 'post', 'body' => [ 'query' => [ 'match' => [ 'author' => 'Luiz' ] ] ]];

$results = $client->search($params);

$params = ['index'] = 'phpsc';$params = ['my_type'] = 'post';$params = ['body']['query']['match']['author' ] = 'Luiz';

$results = $client->search($params);

Conclusões - O que não fazer...

Não use Guzzle, o Elasticsearch oferece o cliente PHP que já empacota o Guzzle e adiciona outras ferramentas

Bulk e Msearch já encapsulado

Tratamento de valores máximos

Uso do cluster

Não faça buscas em chamadas separadas (aumenta muito a latência). Prefira msearch ou buscas multi-índice

Mescar busca no Elasticsearch com buscas em MySQL

Normalizar

Cuidado com os analisadores e com o schemaless

Conclusões - Elasticsearch 2.0

Na verdade já estamos no 2.2

Grandes novidades:

Fim dos filtros

Pipeline de agregações

Groovy para script no lugar de MVEL

Features removidas:

RIVERS já não existem! Muito blogs ainda estão por aí falando disso…

Cuidado com o mapeamento

Mudanças na indexação como parent/child

Filtros!!!

Delete by query!

Conclusões

Sem dúvida a melhor opção para busca textual

Interessante também para analytics e dados georeferenciados

O cliente PHP é maduro e deve ser usado

Muitas outras features podem ser exploradas:

Highlight, outras agregações, script ...

Cuidado com os blogs, apresentações e artigos antigos, a evolução do Elasticseach é muito rápida

Existem outros clientes:http://elastica.io/elastica-vs-elasticsearch-php/

http://www.lcm.com.br/site/#/livros/detalhesLivro/explorando-elasticsearch-com-java---introducao-ao-desenvolvimento-para-big-data.html

Outras possibilidades - Analytics

Client AnalyticsAPI

Elasticsearch+

Kibana

CustomerSuccess

Usuários Decision makers

Usuários

ProductOwner

Usuários

Outras possibilidades - Georeferência

Client AnalyticsAPI

Elasticsearch+

Kibana

CustomerSuccess

Usuários Decision makers

Usuários

ProductOwner

Usuários

Temos vagas :)

Desenvolvedor PHP Seniorhttps://socialbase.workable.com/jobs/175261