O Elasticsearch právě píši seriál, který určitě stojí za prozkoumání!
Elasticsearch je škálovatelné úložiště umožňující nejen fultextové vyhledávání v reálném čase. Využít se dá několika způsoby, primárně byl ale vytvořen právě pro vyhledávání. Pokud máte data v MySQL nebo jiné relační databázi a zjišťujete, že vyhledávání pomocí LIKE
už vám nestačí, nasazení Elasticsearch může být další logický krok.
Trocha motivace úvodem
Co vám tedy Elasticsearch nabízí a na co jej můžete použít? Pokusím se to shrnout ve třech bodech:
1. Elasticsearch jako fulltextové vyhledávání
S pomocí volně dostupných slovníků můžete například vyhledávat klíčové slovo nehledě na skloňování, nebo naimplementovat našeptávač, "měli jste na mysli" a další pokročilé nástroje. Elasticsearch je postaven nad Apache Lucene a plně jej využívá.
2. Elasticsearch jako rychlé distribuované úložiště
Do Elasticsearch můžete uložit jakýkoli dokument ve formátu JSON. Pokud vám pak běží na více strojích, jsou vytvářeny kopie dokumentů a o data tak v případě výpadku nebo poruchy některého z serverů nepříjdete. Navíc je pro většinu výsledků používána cache, takže jsou odpovědi opravdu rychlé (za cenu pomalejšího ukládání).
3. Elasticsearch jako analytický nástroj
V kombinaci s nástrojem Kibana je možné Elasticsearch využít jako pokročilý analytický nástroj poskytující reporty v reálném čase. Můžete tak do Elasticsearch ukládat například access log webového serveru a v Kibaně pak vytvořit grafy s počty přístupů, mapy a další statistiky.
Instalace Elasticsearch
1. Stažení
Pro použití v Nette projektu je spuštění otázkou několika minut. Nejprve navštivte stránky společnosti Elastic a v sekci downloads stáhněte aktuální verzi v zip archivu:
Pokud budete chtít rozběhnout Elasticsearch na serveru s OS Linux, doporučuji využít repozitářů - dojde také k instalaci init skriptů. ZIP archiv rozbalte do vaší oblíbené složky (v mém případě Downloads) a vznikne adresářová struktura podobná této:
2. Konfigurace
Před samotným spuštěním doporučuji upravit konfiguraci v souboru elasticsearch.yml (druhá šipka). Otevřete jej v libovolném editoru - jde o prostý textový soubor. Vzorová konfigurace pro lokální vývoj by mohla vypadat takto:
cluster.name: mylocalcluster
node.name: "My Node"
node.local: true
index.number_of_shards: 1
index.number_of_replicas: 0
Pokusím se vysvětlit jednotlivé řádky konfigurace.
cluster.name
je název clusteru, ve kterém se daný uzel (node) nachází. Elasticsearch sám prozkoumává síť a snaží se připojit ostatní uzly se stejným jménem cluster.name
do jednoho clusteru. Změnou tak předejdete tomu, že se vám Elasticsearch chová podivně, pokud jej používá více vývojářů na lokální síti.
node.name
je název uzlu který spouštíte, slouží pro jeho jednoznačnou identifikaci například v pluginu kopf. Pokud necháte parametr prázdný, vygeneruje se náhodné jméno.
node.local
umožní pouze lokální přístup k Elasticsearch. Pozor na bezpečnost, pokud necháte na produkci zvenčí dostupný port 9200 - i tam se může hodit "lokální" přístup k nodu.
index.number_of_shards
a index.number_of_replicas
nemá smysl pro lokální vývoj nastavovat jinak. Pokud vám vypadne jediný počítač, na kterém máte data, je jedno v kolika kopiích byla uložena :). Při nasazení na produkci doporučuji rozmyslet nastavení index.number_of_shards
, protože po vytvoření indexu jej již nezměníte.
3. Spuštění
Před spuštěním se ujistěte, že máte nainstalovanou javu, pokud ne, bude třeba ji stáhnout. Nyní spusťte soubor elasticsearch
ve složce bin (první šipka v obrázku s rozbaleným archivem). Můžete tak provést z konzole:
$ pwd
/Users/ludekvesely/Downloads/elasticsearch-1.7.1
$ ./bin/elasticsearch
To že se povedlo Elasticsearch spustit ověříte na adrese http://localhost:9200. Nové verze vznikají velmi rychle, nelekejte se tedy mé starší verze 1.5.2. ;-)
Vytvoření Nette projektu
Předpokládám že s Nette již máte zkušenosti a pravděpodobně jen chcete využít možností Elasticsearch v existujícím projektu. Pokud přesto nemáte žádný projekt vytvořený, nainstalujte si composer a následně pomocí příkazu
composer create-project nette/web-project
cd web-project
chmod -R a+rw temp log
Vytvořte prázdný projekt. Tato varianta je od verze Nette 2.3 preferovaná před nette/sandbox, více na fóru Nette. Projekt přesuňte do veřejně přístupného adresáře vašeho webového serveru a po přístupu na soubor index.php ve složce web-project/www byste měli vidět úvodní obrazovku:
Instalace Kdyby/ElasticSearch
Otevřte terminál ve složce s projektem a zadejte příkaz
composer require kdyby/elastic-search
Nyní se nainstalovaly knihovny ruflin/elastica (samotná knihovna pracující s Elasticsearch) a kdyby/elastic-search (napojení na Nette). Zaktualizovaly se také soubory composer.json a composer.lock.
Dále je třeba rozšíření zaregistrovat v Nette a nakonfigurovat. To je maximálně jednoduché - do souboru app/config/config.neon
přidejte následující řádky:
extensions:
search: Kdyby\ElasticSearch\DI\SearchExtension
search:
host: 127.0.0.1
port: 9200
No a to je vlastně všechno! Nyní si stačí kdekoli vyžádat Kdyby\ElasticSearch\Client
, která dědí od Elastica\Client
a s připojením dále pracovat podle dokumentace knihovny Elastica.
Použití knihovny Elastica v Nette aplikaci
Ve vzorové aplikaci pro zachování jednoduchosti ukáži použití v již vytvořeném presenteru HomepagePresenter.php
, ve vaší aplikaci ale tuto logiku doporučuji přenést do modelu. Otevřte tedy zmíněný soubor HomepagePresenter.php
a do třídy HomepagePresenter
přidejte:
private $client;
public function __construct(\Kdyby\ElasticSearch\Client $client)
{
$this->client = $client;
}
Nyní můžete využívat připojení k Elasticsearch pomocí proměnné $client
. Například můžu nejprve vytvořit index s názvem my-index
, nastavím mu počet shardů roven jedné a budu pracovat s type nazvaným data
.
$index = $this->client->getIndex('my-index');
$index->create(['number_of_shards' => 1]);
$type = $index->getType('data');
Následně mohu definovat mapování. Například chci, aby se pro koaždé pole nazvané @timestamp
použil datový typ datum:
$mapping = new \Elastica\Type\Mapping();
$mapping->setType($type);
$mapping->setParam('dynamic_templates', [
['template_timestamp' => [
'match' => '@timestamp',
'mapping' => [
'type' => 'date',
'format' => 'date_time_no_millis'
]
]]
]);
$mapping->send();
$type->setMapping($mapping);
Nyní lze zaindexovat dokument, v tomto příkladu pole $raw
:
$raw = [
'name' => 'Nette',
'year' => 2000
];
$document = new \Elastica\Document(1, $raw);
$type->addDocument($document);
$index->refresh();
Tím jsme dokument zaindexovali do Elasticsearch a měl by být vyhledatelný. Ověřit to můžeme jednoduchým vyhledáním všech dokumentů:
foreach ($type->search([])->getResults() as $result) {
dump($result->getSource());
}
Výstupem (http://localhost/web-project/www/) by pak měl být námi zaindexovaný dokument:
array (2)
name => "Nette" (5)
year => 2000
Výsledný soubor HomepagePresenter.php
by pak měl vypadat takto:
<?php
namespace App\Presenters;
use Nette;
class HomepagePresenter extends Nette\Application\UI\Presenter
{
/**
* @var \Kdyby\ElasticSearch\Client
*/
private $client;
public function __construct(\Kdyby\ElasticSearch\Client $client)
{
$this->client = $client;
}
public function actionDefault()
{
// name of index is 'my-index'
$index = $this->client->getIndex('my-index');
// create index with single shard
$index->delete();
$index->create(['number_of_shards' => 1]);
// name of type is 'data'
$type = $index->getType('data');
// put mappings (every field called @timestamp will be stored as a date)
$mapping = new \Elastica\Type\Mapping();
$mapping->setType($type);
$mapping->setParam('dynamic_templates', [
['template_timestamp' => [
'match' => '@timestamp',
'mapping' => ['type' => 'date', 'format' => 'date_time_no_millis']
]]
]);
$mapping->send();
$type->setMapping($mapping);
// index an array into es
$raw = [
'name' => 'Nette',
'year' => 2000
];
$document = new \Elastica\Document(1, $raw);
$type->addDocument($document);
// refresh es index
$index->refresh();
// now we can search indexed document
foreach ($type->search([])->getResults() as $result) {
dump($result->getSource());
}
$this->terminate();
}
}
Kam dál?
Jsme u konce návodu jak rozběhnout knihovnu Kdyby/Elasticsearch v Nette projektu. Pro další informace o Elasticsearch doporučuji přímo web společnosti Elastic a jejich oficiální dokumentaci, pokud máte radši tištěnou literaturu, tak by měla být dobrá kniha The Definitive Guide. Pro práci s knihovnou Elastica je veškeré podrobné info na jejich webu elastica.io. Zdrojové kódy knihovny Kdyby/ElasticSearch pak naleznete na githubu.