Elastic Elasticsearch

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 11:25, 9 января 2019.
Elasticsearch
Elasticsearch logo.png
Разработчики: Shay Banon
Постоянный выпуск: 6.5.0
Написана на: Java
Операционная система: Кроссплатформенная
Лицензия: Apache License 2.0
Веб-сайт elastic.co/products/elasticsearch
Elasticsearch BV
Industry разработка ПО
Headquarters Амстердам, Голландия
Services Elasticsearch commercial solutions
Website elastic.co

Elasticsearh (в дальнейшем для сокращения часто будет обозначаться как "ES") – это масштабируемый полнотекстовый поисковый и аналитический движок с открытым исходным кодом. Он позволяет хранить большие объемы данных,проводить среди них быстрый поиск и аналитику (почти в режиме реального времени). Как правило, он используется в качестве базового механизма/технологии, которая обеспечивает работу приложений со сложными функциями и требованиями к поиску. Elasticsearch использует в качестве поисковой основы библиотеку Lucene, которая написана на языке Java и доступна для многих платформ. Все неструктурированные данные хранятся в формате JSON, что автоматически делает ES базой данных NoSQL. Но в отличие от других баз данных NoSQL, ES предоставляет возможности поиска и многие другие функции. [Источник 1]

Особенности

  • Масштабируемость и отказоустойчивость — Elasticsearch легко масштабируется. К уже имеющейся системе можно на ходу добавлять новые серверы, и поисковый движок сможет сам распределить на них нагрузку. При этом данные будут распределены таким образом, что при отказе какой-то из нод они не будут утеряны и сама поисковая система продолжит работу без сбоев.
  • Мультиарендность (англ. multitenancy) — возможность организовать несколько различных поисковых систем в рамках одного объекта Elasticsearch. Организацию можно проводить динамически.
  • Операционная стабильность — на каждое изменение данных в хранилище ведется логирование сразу на нескольких ячейках кластера для повышения отказоустойчивости и сохранности данных в случае разного рода сбоев.
  • Отсутствие схемы (англ. schema-free) — Elasticsearch позволяет загружать в него обычный JSON-объект. Далее индексация и добавление в базу поиска производится автоматически. Таким образом, обеспечивается быстрое прототипирование.

Применение

Вот несколько примеров того, где может быть использован Elasticsearch:

  • Вы запускаете интернет-магазин, где вы позволяете своим клиентам искать продукты, которые вы продаете. В этом случае Elasticsearch можно использовать для хранения всего каталога продуктов и инвентаря, а также для поиска и автозаполнения предложений по ним.
  • Вы хотите собирать данные журналов или транзакций и анализировать и анализировать эти данные для поиска тенденций, статистики, обобщений или аномалий. В этом случае можно использовать Logstash (часть стека Elasticsearch/Logstash/Kibana) для сбора, агрегирования и анализа данных, а затем использовать Logstash для передачи этих данных в Elasticsearch. После того, как данные находятся в Elasticsearch, вы можете запускать поиск и агрегирование для поиска любой интересующей вас информации.
  • Вы запускаете платформу оповещения о цене, которая позволяет подкованным в цене клиентам указать правило вроде "Я заинтересован в покупке конкретного электронного гаджета, и я хочу получать уведомления, если цена гаджета упадет ниже $X от любого поставщика в течение следующего месяца". В этом случае вы можете соскоблить цены поставщиков, подтолкнуть их в Elasticsearch и использовать его возможность обратного поиска (перколятор), чтобы соответствовать движениям цен на запросы клиентов и в конечном итоге вытолкнуть оповещения клиенту, как только совпадения будут найдены.
  • У вас есть потребности в аналитике / BI, и вы хотите быстро исследовать, анализировать, визуализировать и задавать специальные вопросы по большому количеству данных (подумайте о миллионах или миллиардах записей). В этом случае можно использовать Elasticsearch для хранения данных, а затем использовать Kibana (часть стека Elasticsearch/Logstash/Kibana) для создания пользовательских панелей мониторинга, которые могут визуализировать важные для вас аспекты данных. Кроме того, можно использовать функцию агрегирования Elasticsearch для выполнения сложных запросов бизнес-аналитики к данным. [Источник 3]


Установка Elasticsearch

Для установки ES потребуется Java. Разработчики рекомендуют установить версии Java новее, чем Java 8 update 20 или Java 7 update 55. Дистрибутив ES доступен на сайте разработчика. После распаковки архива нужно запустить bin/elasticsearch. Для удобства запомним адрес в переменную export ES_URL=$(docker-machine ip dev):9200

export ES_URL=localhost:9200
curl -X GET $ES_URL

Получаем приблизительно такой ответ:

{
    "name" : "Heimdall",
    "cluster_name" : "elasticsearch",
    "version" : {
      "number" : "2.2.1",
      "build_hash" : "d045fc29d1932bce18b2e65ab8b297fbf6cd41a1",
      "build_timestamp" : "2016-03-09T09:38:54Z",
      "build_snapshot" : false,
      "lucene_version" : "5.4.1"
    },
   "tagline" : "You Know, for Search"
}

Безопасность Elasticsearch

У Elasticsearch нет никакой встроенной системы авторизации и ограничения прав доступа..После установки он по умолчанию вешается на порт 9200 на все доступные интерфейсы, что делает возможным не только полностью увести все, что находится в поисковой базе, но и, чисто теоретически, через обнаруженную дырку залезть в систему. К теме сохранности данных также стоит упомянуть про бэкапы. Возможности резервного копирования и восстановления встроены в сам Elasticsearch, причем довольно интересно. Перед началом создания резервных копий нужно эластику сообщить, куда они будут складываться. В местных терминах это называется «создать репозиторий»:

curl -XPUT 'http://localhost:9200/_snapshot/my_backup' -d '{ 
    "type": "fs", 
    "settings": { 
       "location": "/es-backup", 
        "compress": true 
    } 
}'
  • type — тип хранилища, куда они будут складываться. Из коробки есть только файловая система. С помощью дополнительных плагинов можно реализовать заливку на AWS S3, HDFS и Azure Cloud;
  • location — куда сохранять новые бэкапы;
  • compress — сжимать ли бэкапы. Толку не очень много, так как по факту сжимает только метаинформацию, а файлы данных остаются несжатыми. По умолчанию включено.

После того как создан репозиторий, можно начать бэкапиться:

curl -XPUT "localhost:9200/_snapshot/my_backup/snapshot_1?wait_for_completion=true"

Такой запрос создает бэкап с названием snapshot_1 в репозитории my_backup. Восстановить данные можно следующим образом:

curl -XPOST "localhost:9200/_snapshot/my_backup/snapshot_1/_restore"

Причем снимки состояния делаются инкрементальные. То есть в первый раз создается полный бэкап, а далее при последующих бэкапах фиксируется только разница состояния между текущим моментом и моментом предыдущего бэкапа [Источник 4]

Индексация

Добавим документ c id 1 типа post в индекс blog. ?pretty указывает, что вывод должен быть читаемым.

curl -XPUT "$ES_URL/blog/post/1?pretty" -d' 
{ 
  "title": "Веселые котята", 
  "content": "<p>Смешная история про котят<p>", 
  "tags": [ 
    "котята", 
    "смешная история" 
  ], 
  "published_at": "2014-09-12T20:44:42+00:00" 
}' 

ответ сервера:

{
  "_index" : "blog",
  "_type" : "post",
  "_id" : "1",
  "_version" : 1,
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "created" : false
}

ES автоматически создал индекс blog и тип post. Можно провести условную аналогию: индекс — это база данных, а тип — таблица в этой БД. Каждый тип имеет свою схему — mapping, также как и реляционная таблица. Mapping генерирутся автоматически при индексации документа. Получим mapping всех типов индекса blog:

curl -XGET "$ES_URL/blog/_mapping?pretty"

Запросы

Извлечение документа по его id

Извлечем документ с id 1 типа post из индекса blog:

curl -XGET "$ES_URL/blog/post/1?pretty"
{
  "_index" : "blog",
  "_type" : "post",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "_source" : {
    "title" : "Веселые котята",
    "content" : "<p>Смешная история про котят<p>",
    "tags" : [ "котята", "смешная история" ],
    "published_at" : "2014-09-12T20:44:42+00:00"
  }
}

В ответе появились новые ключи: _version и _source. Вообще, все ключи, начинающиеся с _ относятся к служебным.

Ключ _version показывает версию документа. Он нужен для работы механизма оптимистических блокировок. Например, мы хотим изменить документ, имеющий версию 1. Мы отправляем измененный документ и указываем, что это правка документа с версией 1. Если кто-то другой тоже редактировал документ с версией 1 и отправил изменения раньше нас, то ES не примет наши изменения, т.к. он хранит документ с версией 2.

Ключ _source содержит тот документ, который мы индексировали. ES не использует это значение для поисковых операций, т.к. для поиска используются индексы. Для экономии места ES хранит сжатый исходный документ. Если нам нужен только id, а не весь исходный документ, то можно отключить хранение исходника.[Источник 5]

Сортировка

Найдем последний пост по дате публикации и извлечем поля title и published_at:

curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
  "size": 1,
  "_source": ["title", "published_at"],
  "sort": [{"published_at": "desc"}]
}'
{
  "took" : 8,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 3,
    "max_score" : null,
    "hits" : [ {
      "_index" : "blog",
      "_type" : "post",
      "_id" : "1",
      "_score" : null,
      "_source" : {
        "title" : "Веселые котята",
        "published_at" : "2014-09-12T20:44:42+00:00"
      },
      "sort" : [ 1410554682000 ]
    } ]
  }
}

size ограничивает кол-во документов в выдаче. total показывает общее число документов, подходящих под запрос. sort в выдаче содержит массив целых чисел, по которым производится сортировка. Т.е. дата преобразовалась в целое число.

Фильтры

Фильтрация по дате

Используем запрос range в контексте filter:

curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
  "filter": {
    "range": {
      "published_at": { "gte": "2014-09-01" }
    }
  }
}'

Получим посты, опубликованные 1ого сентября или позже.

Фильтрация по тегам

Используем term query для поиска id документов, содержащих заданное слово. Например, найдем все документы, в поле tags которых есть элемент 'котята'

curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
  "_source": [
    "title",
    "tags"
 ],
  "filter": {
    "term": {
      "tags": "котята"
    }
  }
}'
{
  "took" : 9,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 1.0,
    "hits" : [ {
      "_index" : "blog",
      "_type" : "post",
      "_id" : "1",
      "_score" : 1.0,
      "_source" : {
        "title" : "Веселые котята",
        "tags" : [ "котята", "смешная история" ]
      }
    }, {
      "_index" : "blog",
      "_type" : "post",
      "_id" : "3",
      "_score" : 1.0,
      "_source" : {
        "title" : "Как у меня появился котенок",
        "tags" : [ "котята" ]
      }
    } ]
  }
}

Анализаторы

Анализаторы нужны, чтобы преобразовать исходный текст в набор токенов. Анализаторы состоят из одного Tokenizer и нескольких необязательных TokenFilters. Tokenizer может предшествовать нескольким CharFilters. Tokenizer разбивают исходную строку на токены, например, по пробелам и символам пунктуации. TokenFilter может изменять токены, удалять или добавлять новые, например, оставлять только основу слова, убирать предлоги, добавлять синонимы. CharFilter — изменяет исходную строку целиком, например, вырезает html теги. Главная цель любого анализатора — из длинного предложения, перегруженного ненужными деталями, выжать основную суть и получить список токенов, которые бы ее отражали. Принцип работы конвейера анализатора показан ниже на рисунке 1:

Рисунок 1 – Конвейер анализатора

В ES есть несколько стандартных анализаторов. Например, анализатор russian.[Источник 6]

Воспользуемся api и посмотрим, как анализаторы standard и russian преобразуют строку "Веселые истории про котят":

Пример 1. Используем анализатор standard. (Важно: обязательно нужно перекодировать не ASCII символы)

curl -XGET "$ES_URL/_analyze? pretty&analyzer=standard&text=%D0%92%D0%B5%D1%81%D0%B5%D0%BB%D1%8B%D0%B5%20%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D0%B8%20%D0%BF%D1%80%D0%BE%20%D0%BA%D0%BE%D1%82%D1%8F%D1%82"

ответ сервера:

{
  "tokens" : [ {
    "token" : "веселые",
    "start_offset" : 0,
    "end_offset" : 7,
    "type" : "<ALPHANUM>",
    "position" : 0
  }, {
    "token" : "истории",
    "start_offset" : 8,
    "end_offset" : 15,
    "type" : "<ALPHANUM>",
    "position" : 1
  }, {
    "token" : "про",
    "start_offset" : 16,
    "end_offset" : 19,
    "type" : "<ALPHANUM>",
    "position" : 2
  }, {
    "token" : "котят",
    "start_offset" : 20,
    "end_offset" : 25,
    "type" : "<ALPHANUM>",
    "position" : 3
  } ]
}

Пример 2. Используем анализатор russian

curl -XGET "$ES_URL/_analyze?pretty&analyzer=russian&text=%D0%92%D0%B5%D1%81%D0%B5%D0%BB%D1%8B%D0%B5%20%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D0%B8%20%D0%BF%D1%80%D0%BE%20%D0%BA%D0%BE%D1%82%D1%8F%D1%82"

ответ сервера:

{
  "tokens" : [ {
    "token" : "весел",
    "start_offset" : 0,
    "end_offset" : 7,
    "type" : "<ALPHANUM>",
    "position" : 0
  }, {
    "token" : "истор",
    "start_offset" : 8,
    "end_offset" : 15,
    "type" : "<ALPHANUM>",
    "position" : 1
  }, {
    "token" : "кот",
    "start_offset" : 20,
    "end_offset" : 25,
    "type" : "<ALPHANUM>",
    "position" : 3
  } ]
}

Стандартный анализатор разбил строку по пробелам и перевел все в нижний регистр, анализатор russian — убрал не значимые слова, перевел в нижний регистр и оставил основу слов.

Нечеткий поиск

Обработка естественных языков — это работа с постоянными неточностями. По большей части поисковые движки пытаются анализировать грамматические структуры различных языков, осваивать определенные паттерны, характерные для того или иного языка. Но поисковая система постоянно сталкивается с запросами, выходящими за рамки устоявшихся правил орфографии и морфологии. Чаще всего это либо опечатки, либо банальная безграмотность. Самый простой пример нечеткого поиска — это знаменитое «Возможно, Вы имели в виду…» в Гугле. Когда человек ищет «пгода вИ кутске», а ему показывают погоду в Иркутске.

Основой нечеткого поиска является расстояние Дамерау — Левенштейна — количество операций вставки/удаления/замены/транспозиции для того, чтобы одна строка совпала с другой. Например, для превращения «пгода вИ кутске» в «погода в Иркутске» такое расстояние было бы равно трем — две вставки и одна замена.

При работе с нечетким поиском также не стоит забывать и о том, как Elasticsearch (да и любой другой поисковый движок в принципе) работает изнутри. Все данные, загружаемые в индекс, сперва проходят обработку анализатором, лемматизацию, стемминг. В индекс уже складываются только «обрывки» исходных данных, содержащие максимум смысла при минимуме знакового объема. И уже по этим самым обрывкам впоследствии проводится поиск, что при использовании нечеткого поиска может давать довольно курьезные результаты.

Elasticsearch поддерживает несколько различных способов нечеткого поиска:

Таблица 1 – Способы нечеткого поиска
Параметр Описание
match query + fuzziness option Добавление параметра нечеткости к обычному запросу на совпадение. Анализирует текст запроса перед поиском;
fuzzy query Нечеткий запрос. Лучше избегать его использования. Больше похож на поиск по стеммам. Анализ текста запроса перед поиском не производится;
fuzzy_like_this/fuzzy_like_this_field Запрос, аналогичный запросу more_like_this, но поддерживающий нечеткость. Также поддерживает возможность анализа весов для лучшего ранжирования результатов поиска;
suggesters Предположения — это не совсем тип запроса, скорее другая операция, работающая изнутри на нечетких запросах. Может использоваться как совместно с обычными запросами, так и самостоятельно.

Полнотекстовый поиск с поддержкой выражений

Найдем документы, в которых встречается слово 'истории'

curl -XPOST "$ES_URL/blog2/post/_search?pretty" -d'
{
  "query": {
   "simple_query_string": {
    "query": "истории",
    "fields": [
      "title^3",
       "tags^2",
        "content"
     ]
    }
  }
}'
  • query -> simple_query_string -> query содержит поисковый запрос;
  • поле title имеет приоритет 3;
  • поле tags имеет приоритет 2;
  • поле content имеет приоритет 1.

Приоритет используется при ранжировании результатов.

Так как мы используем анализатор с "русским" анализатором, то этот запрос вернет все документы, хотя в них встречается только слово 'история'.

Также запрос может содержать специальные символы:

Таблица 2 – Синтаксис запроса
Символ Описание
+ символ, позволяющий находить документы по конкретным двум или более словам
I символ, позволяющий находить документы по одному из искомых слов
- символ, позволяющий находить документы без указанного искомого слова

Установка Elasticsearch

Пользователи

Примечательные пользователи Elasticsearch[Источник 7]:

Примечания

  1. Homer, Alex. "Set up and administration for Microsoft Code Search in Visual Studio Team Services and Team Foundation Server". www.visualstudio.com. Retrieved 2017-02-23. 
  2. Horohoe, Chad (2014-01-06). "Wikimedia moving to Elasticsearch". Wikimedia blog. Retrieved 2014-02-21. 
  3. "Adding Context to Queries: The Story Behind Adobe’s API and UI". www.elastic.co. Retrieved 2016-09-03. 
  4. "From Hackathon to Production: Elasticsearch @ Facebook". www.elastic.co. Retrieved 2016-05-24. 
  5. "StumbleUpon | Developer Blog". StumbleUpon.com. Retrieved 2014-02-21. 
  6. "Blog of Data". mozilla.org. Retrieved 25 March 2015. 
  7. "ElasticSearch helps Mozilla Metrics team". Pedroalves-bi.blogspot.com. Retrieved 2014-02-04. 
  8. "Full Text Search on Quora". Quora.com. Retrieved 2014-02-04. 
  9. "What programming language was Quizlet built on? - Quora". www.quora.com. Retrieved 2016-12-30. 
  10. "foursquare now uses Elastic Search (and on a related note: Slashem also works with Elastic Search)! | Foursquare Engineering Blog". Engineering.foursquare.com. Retrieved 2014-02-21. 
  11. "Oculus: The metric correlation component of Etsy's Kale system". Github.com. Retrieved 2014-02-04. 
  12. Petar Djekic. "Architecture behind our new Search and Explore experience". Backstage.soundcloud.com. Retrieved 2014-02-04. 
  13. "A Whole New Code Search". Github.com. 2013-01-23. Retrieved 2014-02-21. 
  14. "openFDA - About the API". FDA.gov. 
  15. "Needle in a haystack - Using Elasticsearch to run the Large Hadron Collider of CERN". medium.com. 
  16. Craver, Nick (22 November 2013). "What it takes to run Stack Overflow". Retrieved 2 October 2014. 
  17. "Center for Open Science". 
  18. Pritzker, Yan (8 October 2014). "How we switched elasticsearch clusters without anybody noticing". Reverb Blog. 
  19. "The Netflix Tech Blog: Introducing Raigad - An Elasticsearch Sidecar". 
  20. Steinberger, Simon (1 June 2014). "Advanced Image Search on Pixabay". Retrieved 3 May 2015. 
  21. "Lichess.org". Lichess.org. Retrieved 2016-12-18. 

Источники

  1. Начало работы с Elasticsearch // Nuancesprog.ru [2018-2018]. Дата обновления: 13.06.2018 URL: https://nuancesprog.ru/p/1818/ (дата обращения: 19.12.2018).
  2. Учимся работать с Elasticsearch // Xakep [2015-2018]. Дата обновления: 11.06.2015. URL: https://xakep.ru/2015/06/11/elasticsearch-tutorial/ (дата обращения: 19.12.2018).
  3. Elasticsearch Reference [6.5]  » Getting Started // Elastic.co [2015-2018]. Дата обновления: 20.10.2016 URL: https://www.elastic.co/guide/en/elasticsearch/reference/6.5/getting-started.html (дата обращения: 19.12.2018).
  4. Учимся работать с elasticsearch // Хakep [2015-2018]. Дата обновления: 11.06.2015. URL: https://xakep.ru/2015/06/11/elasticsearch-tutorial/ (дата обращения: 20.12.2018).
  5. Основы elasticsearch // Habr [2016-2018]. Дата обновления: 30.03.2016. URL: https://habr.com/post/280488/ (дата обращения: 04.05.2018).
  6. Анализатор russian // Elastic.co [2015-2018]. Дата обновления: 20.10.2016. URL: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-lang-analyzer.html#russian-analyzer/ (дата обращения: 06.05.2018).
  7. Elasticsearch.org Case Studies // Elastic.co [2015-2018]. Дата обновления: 20.10.2016 URL: http://www.elasticsearch.org/case-studies/ (дата обращения: 24.12.2018).