[Магазин на MODX и ElasticSearch - ч. 2] Основы записи/чтения/обновления данных в ElasricSearch

Итак, в прошлой части мы создали структуру нашей базы со своими хитростями и всем прочим.
Теперь нас должны интересовать 3 основные вещи: запись в Базу данных, чтение данных из базы данных, и обновление.

Запись данных

Запись данных происходит очень просто, например:
curl -XPOST localhost:9200/modx_shop /towar_base /1 -d '{"Артикул":"1","Имя товара":"Товар 1","Цена":"1232","Категория":"1","Парметр_1":"текст","Параметр_2":23,"Параметр_3":25}'


Как можем заметить, первая часть «curl -XPOST localhost:9200/modx_shop /towar_base /1» состоит из уже известных данных, index и type, а теперь о том, что это за 1-ца, на самом деле эта единица не что более, как ID товара. Главная отличительная особенность этой системы, то что в качестве ID может быть всё что угодно, впрочем как и везде. По факту есть одна явная проблема, я так и не научился делать Auto Incriment для id-шника, в принципе как в дальнейшем выяснилось это не проблема, т.к. везде отлично использовался параметр Артикул.

А теперь о второй части,
'{"Артикул":"1","Имя товара":"Товар 1","Цена":"1234","Категория":"1","Парметр_1":"текст","Параметр_2":23,"Параметр_3":25}'

Это всё не более чем простой JSON массив, и именно в этом моменте и возникает проблема с версиями php ниже, чем 5.4, а именно отсутствие вот такого ключа «JSON_UNESCAPED_UNICODE», который позволяет после сформированного ключа, оставлять все значения в читаемом виде, не переводя всё в грубый JSON. И больше этот массив ничем не отличается простого использования команду json_encode

Получение данных

После того, как мы поместили данные, нам нужно их получить. Этот процесс на самом деле самое проще, чем кажется.
curl -XGET localhost:9200/modx_shop /towar_base /1

Главное, на что стоит обратить внимание, это то, что метод изменился с «-XPOST», на «-XGET», а в целом структура не отличается от структуры записи, разве только откидываем часть с данными для записи, т.к. нам их нужно получить, а не записать. И в итоге нам вернётся JSON массив, разобрав который вы можете получить нужные вам данные.

Примерный вариант ответа:
{

"_index" : " modx_shop ",

"_type" : " towar_base",

"_id" : "1",

"_version" : 1,

"found": true,

	"_source" : {

	" Имя товара " : "Товар 1",

	" Категория " : 1,

	" Цена " : "1234",

	…..Дальше все параметры

	}

}


Обновление данных

Ещё одна из наиболее важных вещей — это обновление. Если вам необходимо обновить больше чем 3-4 параметра, или просто лень городить что-то сложное, то процесс, уступающий по скорости на 0.001 секунды от обновления единичного параметра, — это просто запись данных с нуля, т.е. просто выполняем операцию вставки, и наша проблема решена.
В том случае, если вам нужно обновить единичный параметр, то придётся извращаться.
curl -XPOST localhost:9200/modx_shop/towar_base/1/_update -d'{
"script" : "ctx._source.Цена = tag",
"params" : { "tag" : 1232}
}';

В строчке «script»: «ctx._source.Цена = tag» мы указываем, что значение параметра цена принять равным значению tag. Во второй строке мы задаём само значение tag.
Подробнее о методах обновления можно почитать вот здесь
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-update.html
здесь присутствует множество разных красивых вариантов, когда нужно к числу что-то добавить или объединить строки.

Работа с файлами.

Теперь немного о работе с большими файлами. Мною проводились тесты на домашнем сервере, который сложно назвать хорошей боевой машиной.

И выяснилось, что для записи 3-х миллионов товаров в базу грубым методом прямо из php скрипта во время разбора занимает что-то порядка 12 часов. В том случае, если мы все наши команды для обновления загоняем в SH скрипт и пускаем на выполнение, то этот процесс занимает 8 часов. А теперь ещё веселей: если мы загоняем это всё в SH файл и бьём этот же файл на 10-12 частей, то процесс сокращается до 3-ёх часов, как можем заметить, прирост по времени значительный. На нормальной боевой машине не удалось протестировать, т.к. там сразу идею с CSV загубили, т.к. 1С-программисты не умеют загонять всё в CSV. Пришлось работать с XML. Пока база составляет всего 56000 товаров, и, соответственно, с разбивкой на много файлов XML-я пришлось повременить.

Сам процесс разбивки у меня получился своеобразным: я выжидал 28 секунд выполнения скрипта, обновлял страницу и продолжал парсить файл дальше, параллельно формируя один файл для запуска всех скриптов одновременно и много мелких файлов, которые запускает основной SH скрипт.

Пример CSV

Пример скрипта разбора CSV

Пример итога выполнения парсера этого CSV

Пример скрипта XML-я выполнен для ситуации когда нет необходиомсти разбивки на мелкие файлы. Мелких примеров XML-я нет у меня. Да и разбор каждой структуры это не такая уж сложная задача. так что пример только для ознакомления с процессор парсинга длинного файла.

Пример скрипта разбора XML

Итак, подводя итог, в данной части я описал основные принципы чтения, записи и обновления. В следующей части я опишу процесс построения фильтров, для выборки данных.

UPD. Спасибо vanchelo напомнил мне, о не менее важной вещи, а именно об удалении товаров из базы
Удаление
Пример запроса отвечающего за удаление товара.
curl -XDELETE 'http://localhost:9200/modx_shop/towar_base/1'

Кардинально ничем не отличается от запроса получения, только вместо XGET, у нас XDELETE. Мы указываем из какого index, товар с каким id мы удаляем.

UPD 2. В скайпе сообщества MODX в Беларуси, ткнули носом, что не хватает меню.
Меню
  1. Анонс
  2. Часть 1. Общая информация по ElasticSearch (установка, настройка)

12 комментариев

avatar
Топик не читал, а только глянул код работы с ElasticSearch… Почему не стали юзать библиотеку github.com/elasticsearch/elasticsearch-php? Импорт импортом, гонки на скорость и т.п. это все прекрасно, но как данные то будете обновлять? Тоже курлом?
avatar
В первой части я писал о библиотеке, и о том что в момент когда начинал разработку, она ещё не была достаточно гибкой, и если честно не уверен сейчас в её гибкости. При единичных данных не очень большая потеря по скорости при обновлении по единичному товару через библиотеку. Но если много товаров. То как показала практика, курл значительно побеждает. Тестировалось на 3млн товаров.
avatar
Спасибо, видимо упустил. У самого как раз недавно встала необходимость реализации фасетного поиска под приличный объем данных. Но в рамках Laravel, а не MODX. Поэтому однозначно ваш опыт пригодится.
avatar
Слышал о Laravel, многие говорят о нём сейчас. В принципе большая часть информации вообще не будет связана с MODX, там построение меню будет вокруг wayfinder-а, и фильтры вокруг того места где мы храним, хотя можно использовать и TV поле.
avatar
она ещё не была достаточно гибкой
И кстати, в чем именно гибкости не хватило?
avatar
Построение запросов. Когда нужно выбрать n значений параметра через «or», и таких параметров с n значениями штук 15 например. И сразу же одновременно с этим вытаскивать фасеты других параметров, помимо самих товаров.
avatar
Хороший цикл статей.
Кстати ты не забыл про DELETE и PUT?
avatar
Точно про удаление забыл :-( Спасибо большое.
Сейчас допишу по быстрому.
PUT — Это одна из вариций вставки. Но так же допустимо XPOST. Разницы по скорости я лично не заметил. Перед написанием статьи гонял тестами оба варианта, там на миллионе 3 минуты выиграл POST, а второй раз 2 минуты выиграл PUT, так что эти функции примерно равны по скорости.
avatar
Мне интересен фасетный поиск, то что сейчас должно быть в любом вменяемом магазине, ну и конечно нормальный полнотекстовый.

А вообще ты не думал его использовать как основное хранилище? Или задержки большие? Я вот подумываю его заюзать с монгой да и в Elastic есть такая суперовая вещь как River plugins
avatar
Я сейчас думаю. Или так называемый фасетный поиск описать в следующей части, или сложности с директориями. Просто по факту у меня эти вещи оказались взаимосвязанными.
Поиск можно разграничивать правами на чтения для каждого, я назову это ключа. Я не уверен что поддерживает морфологию, русскую так 100% не поддерживает морфологию.
Касаемо хранилища, у нас все товары и заказы только в ElasticSearch хранятся, я что-то прикинул, и решил, что использовать SQL не рационально, учитывая планы на посещаемость у магазина.
avatar
Плохо что через unixsocket не работает
avatar
Не тестировал я через unixsocket, и на мой стыд я не знаю что это такое.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.