Знакомство с Elasticsearch
В этом уроке мы познакомим вас с
Elasticsearch и рассмотрим как связать данный инструмент с PHP. Elasticsearch - это бесплатный поисковый сервер, работающий на основе Apache Lucene. Главное преимущество данного инструмента в том, что он предоставляет возможность осуществить быстрый и гибкий поиск. Так же нам доступен REST API, который позволяет создавать, удалять, изменять и получать данные.
Установка Elasticsearch
Для установки Elasticsearch нам потребуется Java. По умолчанию в Ubuntu её нет, так что сначала добавляем репозиторий.
1 | sudo add-apt-repository ppa:webupd8team/java |
Теперь приступаем непосредственно к установке Java.
1 | sudo apt-get install oracle-java8-installer |
Далее скачиваем Elasticsearch, используя
wget
.
На данный момент версия 1.5.2 является самой стабильной, поэтому мы будем использовать именно её. Если вам нужна какая-то другая версия, то архив релизов можно найти
тут.
Затем распаковываем и запускаем установку.
2 | tar -xf elasticsearch-1.5.2.tar.gz -C es |
Теперь после обращения к адресу
http://localhost:9200
в адресной строке браузера, вы должны увидеть следующее:
03 | "name" : "Rumiko Fujikawa" , |
04 | "cluster_name" : "elasticsearch" , |
07 | "build_hash" : "62ff9868b4c8a0c45860bebb259e21980778ab1c" , |
08 | "build_timestamp" : "2015-04-27T09:21:06Z" , |
09 | "build_snapshot" : false , |
10 | "lucene_version" : "4.10.4" |
12 | "tagline" : "You Know, for Search" |
Использование Elasticsearch
Теперь можем начать наше взаимодействие с Elasticsearch. Для начала давайте установим PHP клиент для работы с Elasticsearch.
1 | composer require elasticsearch/elasticsearch |
Затем создаём новый php файл, который будем использовать для примеров.
2 | require 'vendor/autoload.php' ; |
4 | $client = new Elasticsearch\Client(); |
Индексация документов
Индексация документов осуществляется вызовом метода
index
, который принимает массив аргументов. В нём должно быть три ключа:
body
,
index
и
type
. В ключе
body
будет располагаться массив с данными, которые нужно индексировать. В
index
следует указывать сегмент, где вы собираетесь индексировать данные (что-то типа название базы данных). В type следует указывать категорию документа (что-то типа названия таблицы). Вот пример:
02 | $params [ 'body' ] = array ( |
03 | 'name' => 'Ash Ketchum' , |
08 | $params [ 'index' ] = 'pokemon' ; |
09 | $params [ 'type' ] = 'pokemon_trainer' ; |
11 | $result = $client ->index( $params ); |
Если вывести
$result
, то результат будет такой:
4 | [_type] => pokemon_trainer |
5 | [_id] => AU1Bn51W5l_vSaLQKPOy |
В приведённом примере мы не указали ID документа. В этом случае Elasticsearch автоматически присвоит уникальный ID. Это можно сделать и самим:
02 | $params [ 'body' ] = array ( |
08 | $params [ 'index' ] = 'pokemon' ; |
09 | $params [ 'type' ] = 'pokemon_trainer' ; |
10 | $params [ 'id' ] = '1A-000' ; |
12 | $result = $client ->index( $params ); |
Результат вывода переменной
$result
:
4 | [_type] => pokemon_trainer |
Для индексации документов мы можем использовать как простые массивы, так и вложенные:
02 | $params [ 'body' ] = array ( |
19 | $params [ 'index' ] = 'pokemon' ; |
20 | $params [ 'type' ] = 'pokemon_trainer' ; |
21 | $params [ 'id' ] = '1A-002' ; |
23 | $result = $client ->index( $params ); |
Вложенность может быть какой угодно глубины (однако увлекаться этим не стоит).
Поиск по документам
Для поиска следует использовать метод
get
или
search
:
get
в случа, если вы знаете ID документа. Так же следует отметить, что данный метод возвращает только один документ. Для поиска набора результатов по различным критериям (по полям) следует использовать метод
search()
.
Get
Давайте начнём с метода
get
. Точно так же как метод
index
он принимает массив аргументов. В массиве должны быть ключи
index
,
type
и
id
документа, который вы хотите найти.
2 | $params [ 'index' ] = 'pokemon' ; |
3 | $params [ 'type' ] = 'pokemon_trainer' ; |
4 | $params [ 'id' ] = '1A-001' ; |
6 | $result = $client ->get( $params ); |
Результат поиска:
04 | [_type] => pokemon_trainer |
Поиск по определённым полям
В массиве аргументов для метода
search
следует указать ключи
index
,
type
и
body
. В ключе
body
указываем критерии запроса. Вот как можно вернуть все документы, где возраст равен
15
.
1 | $params [ 'index' ] = 'pokemon' ; |
2 | $params [ 'type' ] = 'pokemon_trainer' ; |
3 | $params [ 'body' ][ 'query' ][ 'match' ][ 'age' ] = 15; |
5 | $result = $client ->search( $params ); |
Результат:
21 | [_type] => pokemon_trainer |
Давайте разберём результат:
took
– время выполнения запроса.
timed_out
– возвращает true
если время выполнения запроса прошло.
_shards
– по умолчанию, Elasticsearch размещает данные по 5 шардам (сегментам). Если значение 5 будет в total
и successful
то каждый шард работает корректно.
hits
содержит результат поиска.
Метод который мы продемонстрировали, позволяет осуществить поиск по глубине равной единице. Если мы хотим искать глубже, то нам следует воспользоваться
bool
запросами. Для этого указываем ключ
bool
в
query
. Теперь в поиске будут задействованы все поля, разделяя их знаком
.
.
1 | $params [ 'index' ] = 'pokemon' ; |
2 | $params [ 'type' ] = 'pokemon_trainer' ; |
3 | $params [ 'body' ][ 'query' ][ 'bool' ][ 'must' ][][ 'match' ][ 'pokemon.psyduck.type' ] = 'water' ; |
4 | $result = $client ->search( $params ); |
Поиск массивами
Так же мы можем осуществлять запросы, используя массивы, указав ключ
bool
, а затем
must
,
terms
. В качестве значения указываем массив значений, который должен быть задействован в поиске. В данном примере ищем документы, где поле
age
равняется 10 и 15.
1 | $params [ 'index' ] = 'pokemon' ; |
2 | $params [ 'type' ] = 'pokemon_trainer' ; |
4 | $params [ 'body' ][ 'query' ][ 'bool' ][ 'must' ][ 'terms' ][ 'age' ] = array (10, 15); |
В данном способе можно применять только линейные массивы.
Поиск по фильтрам
Теперь давайте посмотрим как можно осуществить поиск с применением фильтров. Для фильтрации нужно указать ключ
filtered
, а в качестве значения начальное и конечно число диапазона искомых значений. В данном случае мы будем искать по полю
age
, где значение больше или равно (gte) 11 и меньше или равно (lte) 20.
1 | $params [ 'index' ] = 'pokemon' ; |
2 | $params [ 'type' ] = 'pokemon_trainer' ; |
3 | $params [ 'body' ][ 'query' ][ 'filtered' ][ 'filter' ][ 'range' ][ 'age' ][ 'gte' ] = 11; |
4 | $params [ 'body' ][ 'query' ][ 'filtered' ][ 'filter' ][ 'range' ][ 'age' ][ 'lte' ] = 20; |
5 | $result = $client ->search( $params ); |
OR и AND
При работе с запросами в реляционных СУБД мы часто используем ключевые слова
AND
или
OR
. В Elasticsearch у нас тоже есть такая возможность: для этого просто указываем ключ
and
. Выберем все документы, где возраст age равен 10 и badge равен 8.
1 | $params [ 'index' ] = 'pokemon' ; |
2 | $params [ 'type' ] = 'pokemon_trainer' ; |
4 | $params [ 'body' ][ 'query' ][ 'filtered' ][ 'filter' ][ 'and' ][][ 'term' ][ 'age' ] = 10; |
5 | $params [ 'body' ][ 'query' ][ 'filtered' ][ 'filter' ][ 'and' ][][ 'term' ][ 'badges' ] = 8; |
7 | $result = $client ->search( $params ); |
Если нужно осуществить поиск по одному из этих двух значений, то используйте ключ
or
.
1 | $params [ 'body' ][ 'query' ][ 'filtered' ][ 'filter' ][ 'or' ][][ 'term' ][ 'age' ] = 10; |
2 | $params [ 'body' ][ 'query' ][ 'filtered' ][ 'filter' ][ 'or' ][][ 'term' ][ 'badges' ] = 8; |
Выбор определённого числа результатов
Мы можем ограничить число результатов поиска, используя поле
size
. Пример:
1 | $params [ 'body' ][ 'query' ][ 'filtered' ][ 'filter' ][ 'and' ][][ 'term' ][ 'age' ] = 10; |
2 | $params [ 'body' ][ 'query' ][ 'filtered' ][ 'filter' ][ 'and' ][][ 'term' ][ 'badges' ] = 8; |
Возвращает только один документ.
Постраничное разделение
В реляционных СУБД есть возможность выбирать данные по различным сегментам, используя ключевые слова
LIMIT
и
OFFSET
. В Elasticsearch тоже есть аналоги: ключи
size
и
from
.
from
позволяет нам осуществить выборку с нужного нам “отступа”. Индексация документов начинается с нуля. Вот как мы можем получить вторую страницу результатов:
1 | $params [ 'index' ] = 'pokemon' ; |
2 | $params [ 'type' ] = 'pokemon_trainer' ; |
Редактирование документа
Для обновления данных в документе нам необходимо сначала его извлечь. Для этого указываем
index
,
type
и
id
документа в методе
get
. Текущие данные можно найти в сегменте
_source
. Для обновления данных, просто обращаемся к полям и задаём новые значения. Для сохранения результатов следует вызвать метод update.
02 | $params [ 'index' ] = 'pokemon' ; |
03 | $params [ 'type' ] = 'pokemon_trainer' ; |
04 | $params [ 'id' ] = '1A-001' ; |
05 | $result = $client ->get( $params ); |
08 | $result [ '_source' ][ 'age' ] = 21; |
11 | $result [ '_source' ][ 'pokemon' ] = array ( |
15 | 'Rock Slide' => array ( |
19 | 'Earthquake' => array ( |
27 | $params [ 'body' ][ 'doc' ] = $result [ '_source' ]; |
29 | $result = $client ->update( $params ); |
Результат:
4 | [_type] => pokemon_trainer |
Значение поля
_version
будет увеличиваться каждый раз при вызове метода
update
(в том случае, если хоть одно поле было изменено).
Вы можете подумать, что Elasticsearch сохраняет предыдущие версии документа, но это не так. Данный счётчик просто показывает количество обновлений документа.
Удаление документа
Для удаление документа достаточно вызвать метод
delete
. В массиве аргументов следует указать поля
index
,
type
и
id
.
2 | $params [ 'index' ] = 'pokemon' ; |
3 | $params [ 'type' ] = 'pokemon_trainer' ; |
4 | $params [ 'id' ] = '1A-001' ; |
6 | $result = $client -> delete ( $params ); |
Результат:
5 | [_type] => pokemon_trainer |
Заметка: если вытащить документ, используя метод
get
, а затем его удалить, то может возникнуть ошибка.
Вывод
В этой статье мы рассмотрели как стартануть с Elasticsearch и PHP, используя официальный Elasticsearch клиент. Так же мы рассмотрели как осуществить индексацию документов, организовать поиск, постраничный вывод, обновление и удаление данных.
Elasticsearch - это прекрасный способ добавить в ваше PHP приложение гибкий и быстрый поиск.
Комментариев нет :
Отправить комментарий