Elasticsearch - поисковая система

Устанока

nano ~/elasticsearch-install.sh

#!/usr/bin/sh VERSION=5.5.2 apt-get install openjdk-7-jdk rm /etc/alternatives/java ln -s /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java /etc/alternatives/java wget https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/deb/elasticsearch/$VERSION/elasticsearch-$VERSION.deb sudo dpkg -i elasticsearch-$VERSION.deb # be sure you add "action.disable_delete_all_indices" : true to the config!! # start script sudo /etc/init.d/elasticsearch restart sudo ln -s /usr/share/elasticsearch/bin/plugin /usr/bin/plugin # ------------------------------------------------------------------------------------ # if you want to remove it: #sudo dpkg -r elasticsearch # binaries & plugin #/usr/share/elasticsearch/bin # log dir #/var/log/elasticsearch # data dir #/var/lib/elasticsearch # config dir #/etc/elasticsearch # prepare ElasticSearch UI #sudo apt-get install apache2 #sudo mkdir /var/www/ui #sudo chown -R ubuntu.www-data /var/www # now copy ES-HEAD to /var/www/ui

Установка и настройка Elasticsearch

Установите максимальный размер открытых дескрипторов файла для пользователя от 32k до 64k

nano /etc/sysctl.conf

vm.max_map_count = 262144

Если возможно, отключите свопинг памяти для процессов Elasticsearch. Обратите внимание, что в виртуальных средах это может привести к неожиданным результатам.

Установите значение -Xms равным -Xmx (то же самое что установить значение переменной среды ES_HEAP_SIZE).

Оставьте некоторое количество памяти, чтобы кеш операционной системы мог использовать его для Lucene.

Elasticsearch JVM не должен занимать больше половины всего объема памяти.

Подробнее...

Проверка работоспособности сервера

$ curl -XGET http://localhost:9200/_stats/?pretty $ curl -XGET http://localhost:9200/_nodes/?pretty $ curl --silent -XGET "http://localhost:9200/_snapshot/_all"
$ curl --silent -XGET "http://localhost:9200/_cat/nodes?pretty" mbp-mirocow 192.168.1.147 11 78 6.88 d * Mirocow

Создание дампа / Dump create

English: https://gist.github.com/lucidlibrary/188d6ff895e56c83dea3

Добавляем путь до сохранения снапшотов в конфигурационный файлnano /usr/local/etc/elasticsearch/elasticsearch.yml path.repo: ["/usr/local/var/elasticsearch/snapshot"]

Регистрация

$ curl -XPUT 'http://localhost:9200/_snapshot/backup' -d '{ "type": "fs", "settings": { "location": "/usr/local/var/elasticsearch/snapshot", "compress": true } }'

где:

backup - название репозитория

/usr/local/var/elasticsearch/snapshot - папка с содержанием самого репозитория

Проверка регистрации

$ curl -XGET "http://localhost:9200/_snapshot/_all?pretty"

ответ от elasticsearch

{ "backup" : { "type" : "fs", "settings" : { "compress" : "true", "location" : "/usr/local/var/elasticsearch/snapshot/backup" } } }

Проверка целостности

$ curl -XPOST "http://localhost:9200/_snapshot/backup/_verify

ответ от elasticsearch

{"nodes":{"zKsDO_G3SlCdbLlhVmgLKA":{"name":"Vapor"}}}

Создание snapshot / Backup

$ curl -XPUT "http://localhost:9200/_snapshot/backup/my_index/?wait_for_completion=true"

Где my_index является существующим индексом.

Проверить наличие инднеса можно командой

$ curl --silent -XGET "http://localhost:9200/_stats?pretty"|grep my_index

Удаление регистрации репозитория

$ curl -XDELETE 'http://localhost:9200/_snapshot/backup'

Восстановление / Restore

English: https://gist.github.com/lucidlibrary/188d6ff895e56c83dea3

Настройка

Если ранее небыл зарегистрирован.

$ curl -XPUT 'http://localhost:9200/_snapshot/_restore?wait_for_completion=true' -d '{ "type": "fs", "settings": { "location": "/usr/local/var/elasticsearch/snapshot", "compress": true } }'

где:

backup - название репозитория

/usr/local/var/elasticsearch/snapshot - папка с содержанием самого репозитория

Проверка

$ curl -XPOST http://localhost:9200/_snapshot/backup/_verify?pretty

Восстановление

$ curl -XPOST http://localhost:9200/_snapshot/backup/_restore?pretty

Запрос поиска

Способы запроса

Elasticsearch SDL

GET

Вывод всех документов из индекса

$ curl -XGET 'localhost:9200/test/_search?q=*&pretty'

REST

Вывод всех документов из индекса

$ curl -XPOST 'localhost:9200/1vse/_search?pretty' -d ' { "query": { "match_all": {} } }'

Доступные параметры для REST запросов

$ curl -XPOST 'localhost:9200/1vse/_search?pretty' -d ' { "query": { "match_all": {} }, "size": 1 }'
$ curl -XPOST 'localhost:9200/1vse/_search?pretty' -d ' { "query": { "match": { "title": "Thomson T50E10DHU-01B" } }, "_source": ["title", "category", "brand"] }' $ curl -XPOST 'localhost:9200/1vse/_search?pretty' -d ' { "query": { "match_phrase": { "category": "телевизоры" } }, "_source": ["title", "category", "brand"] }' $ curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "query": { "bool": { "must": [ { "match": { "age": "40" } } ], "must_not": [ { "match": { "state": "ID" } } ] } } }'

Поиск по регулярным выражениям

$ curl -XGET 'http://localhost:9200/_search' -d '{ "filter": { "bool": { "should": [ { "regexp": { "word": "мульт.*" } }, { "regexp": { "word": "фильм.*" } } ], "must_not": { "terms": { "word": ["видео", "скачать"] } } } } }'

Подробнее...

Примеры запросов / Query DSL

$ curl -XGET http://localhost:9200/1vse/product/_search/ -d '{ "size": 10, "query": { "bool": { "should": [ { "function_score": { "weight": 100, "query": { "match": { "product.title": "samsung" } } } }, { "function_score": { "weight": 80, "query": { "match_phrase_prefix": { "product.title": "samsung" } } } } ] } } }'

где:

1vse - название БД

product.title - название таблицы

Создание индексов

Данная операция создаст инжекс test

$ curl -XPUT "http://localhost:9200/test?pretty" { "acknowledged" : true }

Получить список созданых индексов

$ curl --silent -XGET "http://localhost:9200/_cat/indices?pretty"

ответ от elasticsearch

yellow open 1vse 5 1 147785 0 197.3mb 197.3mb yellow open 1vse_logs 5 1 439914 0 1.6gb 1.6gb
$ curl --silent -XGET "http://localhost:9200/_cat/indices?v"

ответ от elasticsearch

health status index pri rep docs.count docs.deleted store.size pri.store.size yellow open 1vse 5 1 147785 0 197.3mb 197.3mb yellow open 1vse_logs 5 1 439914 0 1.6gb 1.6gb

Фильтры

Фильтр worddelimiter

Фильтр worddelimiter разбивает слова на несколько частей. Небольшой пример: представьте, что вы допустили опечатку в предложении “To be or not to be.That is the question”. Если вы обратите внимание, то заметите отсутствие пробела после точки. Без этого фильтра Elasticsearch проиндексирует “be.That” как одно слово - “bethat”. При помощи этого фильтра мы указываем ему индексировать эти слова по отдельности - “be” и “that”.

Примеры:

Фильтр stopwords

Фильтр stopwords состоит из списка слов запрещенных к индексированию. Например он исключает такие слова, как “and”, “a”, “the”, “to” и т.д. Конечно этот список уникален для каждого языка, но существует довольно много заготовок, которые вы можете использовать.

Примеры:

Фильтр snowball

Фильтр snowball используется для группировки слов по их основе. Фильтр применяет набор правил для правильного определения основы слова. Это означает, что разные настройки могут выдавать разные результаты. Например слова “indexing”, “indexable”, “indexes”, “indexation” и т.д. получать основу “index”. Хотелось бы отметить, что вы получите результат “Make my string indexable”, запросив “Indexing string”.

Примеры:

Фильтр elison

Фильтр elison имеет большее значения для некоторых языков (например французский) и не так важен для других (например английский). Он исключает маловажные слова перед индексированием, например “j’attends que tu m’appelles” (Я жду вашего звонка) проиндексируется как “attends que tu appelles” (наконце слова “que” и “tu” будут исключены фильтром stopwords). Как вы видите слова “j’” и “m’” (Я) были удалены из-за настройки фильтра elison.

Примеры:

Фильтр lowercase

Фильтр asciifolding

Заменяет все Unicode символы, не входящие в латинский алфавит на их ascii эквивалент.

Лексеры

nGram

Роль лексера nGram очень высока. Например, наш поиск “funny pony” был разбит на несколько частей. Вот два примера:

Пример 1

"min_gram" : "2",
"max_gram" : "3"

Результат:
fu, fun, un, unn, nn, nny, po, pon, on, ony, ny
2-ой пример с лучшей настройкой:

Пример 2

"min_gram" : "3",
"max_gram" : "20"
Результат:
fun, funn, funny, unn, unny, nny, pon, pony, ony

Анализаторы

По умолчанию в Eldsticseach включен регистрозависимый анализатор поиска. Для его отключения используем ниже следующие настройки в конфигурационом файле elasticsearch.yml

settings: index: analysis: analyzer: string_lowercase: tokenizer: keyword filter: lowercase

Мапинг

$ curl -XGET "http://localhost:9200/1vse_logs/_mapping?pretty=true"

Примеры индексов

settings: index: analysis: analyzer: app_analyzer: type: custom tokenizer: nGram filter : [stopwords, app_ngram, asciifolding, lowercase, snowball, worddelimiter] app_search_analyzer: type: custom tokenizer: standard filter : [stopwords, app_ngram, asciifolding, lowercase, snowball, worddelimiter] tokenizer: nGram: type: "nGram" min_gram: 2 max_gram: 20 filter: snowball: type: snowball language: English app_ngram: type: "nGram" min_gram: 2 max_gram: 20 worddelimiter : type: word_delimiter stopwords: type: stop stopwords: [_french_] ignore_case : true

https://github.com/asyncee/elasticsearch-russian-config

Работа с документом

Подокументно

Получение документа

$ curl -XGET "http://localhost:9200/test/external/key1?pretty"

ответ от elasticsearch

{ "_index" : "test", "_type" : "external", "_id" : "key1", "_version" : 4, "found" : true, "_source": { "body": { "name": "test test", "description": "Description" } } }

Добавление документа / Заполенение индекса

$ curl -XPUT "http://localhost:9200/test/external/key1?pretty" -d ' { "body": {"name": "test"} }'

ответ от elasticsearch

{ "_index" : "test", "_type" : "external", "_id" : "1", "_version" : 1, "created" : true }

Обновление документа

$ curl -XPOST "http://localhost:9200/test/external/key1?pretty" -d ' { "body": { "pice_id": 3, "name": "test test", "description": "Description" } }'

ответ от elasticsearch

{ "_index" : "test", "_type" : "external", "_id" : "1", "_version" : 1, "created" : true }

Частичное обновление документа

$ curl -XPUT "http://localhost:9200/test/external/key1?pretty" -d ' { "body": { "doc": { "name": "test test" } } }'

ответ от elasticsearch

{ "_index" : "test", "_type" : "external", "_id" : "1", "_version" : 1, "created" : true }

Обновление документа с учетом параметров

> v 2.3

$ curl -XPOST 'http://localhost:9200/test/external/_bulk' -d ' { "update": { "_index": "myindex", "_type": "type", "_id": "myid" } }{ "doc": { "field": "new value" } }'

v 2.3 >

$ curl -XPOST 'http://localhost:9200/test/external/_update_by_query' -d ' { "query": { "filtered": { "filter": { "bool": { "must": [ { "term": { "url": "stackoverflow.com" } }, { "missing": { "field": "category" } } ] } } } }, "script" : "ctx._source.category = \"10\";" }'

Получение документа из индекса по ID

$ curl -XGET "http://localhost:9200/test/external/1?pretty"

ответ от elasticsearch

{ "_index" : "test", "_type" : "external", "_id" : "1", "_version" : 3, "found" : true, "_source": { "name": "test" } }

Удаление документа из индекса

Удаление по индексу

$ curl -XDELETE 'localhost:9200/customer/external/2?pretty'

Мы также имеем возможность удалить несколько документов совпавших с условием запроса. Данный пример показывает как удалить все документы из индекса customers, содержащие «John»:

$ curl -XDELETE 'localhost:9200/customer/external/_query?pretty' -d ' { "query": { "match": { "name": "John" } } }'

Работа с частичными данными документа

Настройки elasticsearch.yml

script.update: on
script.mapping: on
script.engine.groovy.file.aggs: on
script.engine.groovy.file.mapping: on
script.engine.groovy.file.search: on
script.engine.groovy.file.update: on
script.engine.groovy.file.plugin: on
script.engine.groovy.indexed.aggs: on
script.engine.groovy.indexed.mapping: on
script.engine.groovy.indexed.search: on
script.engine.groovy.indexed.update: on
script.engine.groovy.indexed.plugin: on
script.engine.groovy.inline.aggs: on
script.engine.groovy.inline.mapping: on
script.engine.groovy.inline.search: on
script.engine.groovy.inline.update: on
script.engine.groovy.inline.plugin: on

Создание массива

$ curl -s -XPOST 'localhost:9200/1vse/product_for_mapping/1/_update' -d '{ "script" : "if(ctx._source.aliases.size() == 0){ctx._source.aliases = [];}" }'

Добавление в массив

$ curl -XPOST 'localhost:9200/1vse/product_for_mapping/1/_update' -d '{ "script" : "ctx._source.aliases += alias", "params" : { "alias" : "Manfrotto MV-M500A" } }'

Удаление из массива

$ curl -s -XPOST 'localhost:9200/1vse/product_for_mapping/1/_update' -d '{ "script" : "for (int i = 0; i < ctx._source.aliases.size(); i++){if(ctx._source.aliases[i] == value){ctx._source.aliases.remove(i);}}", "params" : { "value" : "Manfrotto MVM500A XXX" } }'

https://www.elastic.co/guide/en/elasticsearch/guide/1.x/partial-updates.html

https://www.elastic.co/guide/en/elasticsearch/reference/1.7/modules-scripting.html

https://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-update.html

Пакетная обработка документов

$ curl -XPOST 'localhost:9200/customer/external/_bulk?pretty' -d ' {"index":{"_id":"1"}} {"name": "John Doe" } {"index":{"_id":"2"}} {"name": "Jane Doe" }'

Данный пример обновляет первый документ (с ID равным 1) и затем удаляет второй документ (с ID равным 2) в одной массовой операции:

$ curl -XPOST 'localhost:9200/customer/external/_bulk?pretty' -d ' {"update":{"_id":"1"}} {"doc": { "name": "John Doe becomes Jane Doe" } } {"delete":{"_id":"2"}}'

Параметры выдачи

_source -

_score - Оценка - это числовое значение, которое является относительной мерой того, насколько документ совпадает с поисковым запросом, который мы создали. Большие значения оценки показывают более релевантные (более полно совпадающие) документы, меньшие значение - менее релевантные.

Агрегация

Плагины / Plugins

Elasticsearch plugins

Ошибки / Errors

snapshot_missing_exception:

{"type": "no_such_file_exception","reason/usr/local/var/elasticsearch/snapshot/snap-snapshot.dat"}

SnapshotMissingException:

{"error":"SnapshotMissingException[[backup:snapshot] is missing]; nested: FileNotFoundException[/usr/local/var/elasticsearch/snapshot/snapshot-snapshot (No such file or directory)]; ","status":404}

snapshot не найден, так как дамп создавался с отличным названием снапшота от snapshot

Data too large, data for [@timestamp] would be larger than limit

$ curl -XPOST 'http://localhost:9200/_cache/clear'

Клиенты

Elastica - (https://github.com/ruflin/Elastica) PHP клиент

https://github.com/taskrabbit/elasticsearch-dump - Дампер на nodejs

https://github.com/jprante/elasticsearch-jdbc - JDBC importer for Elasticsearch

https://github.com/toptal/chewy

https://github.com/elastic/elasticsearch-php

https://github.com/elastic/elasticsearch-js

Yii2

https://github.com/yiisoft/yii2-elasticsearch

Дискусии/Форумы

https://discuss.elastic.co/c/in-your-native-tongue/15-category (текущая группа)

https://groups.google.com/forum/#!forum/elasticsearch-ru (бывшая группа)

Документация/Статьи

Elasticsearch in Action.pdf

http://elasticsearch.docwiki.ru/guide/ru/elasticsearch/reference/current/getting-started.html (RUS)

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

http://habrahabr.ru/post/122531/

https://xakep.ru/2015/06/11/elasticsearch-tutorial/

https://habrahabr.ru/company/2gis/blog/213765/

https://habrahabr.ru/company/likeastore/blog/223109/

https://habrahabr.ru/company/likeastore/blog/223109/

Эффективная настройка Elasticsearch

Шпаргалка по оптимизации индексирования в Elasticsearch

http://elasticsearch.docwiki.ru/guide/ru/elasticsearch/reference/current/getting-started.html - (RUS)

http://elasticsearch.docwiki.ru/forum/

https://groups.google.com/forum/#!forum/elasticsearch-ru

http://openness.microsoft.com/ru-cee/blog/2015/05/26/elasticsearch-%D0%BD%D0%B0-azure/

http://victor.4devs.io/ru/others/how-to-improve-on-site-search-on-e-commerce-with-elasticsearch.html

https://makeomatic.ru/blog/tags/ElasticSearch/

http://ru.stackoverflow.com/questions/tagged/elasticsearch

Быстрый полнотекстовый поиск ElasticSearch

ElasticSearch и поиск наоборот. Percolate API

ElasticSearch — агрегация данных

вжhttps://github.com/asyncee/elasticsearch-russian-config

ElasticSearch — mapping и поиск без сюрпризов

Делаем простейший фильтр по свойствам товаров с помощью ElasticSearch на Symfony2

https://habrahabr.ru/post/280488/

ElasticSearch 1.0 — новые возможности аналитики

Elasticsearch — сортируем выдачу руками

Autocomplete / Shingles

http://www.bilyachat.com/2015/07/search-like-google-with-elasticsearch.html

https://qbox.io/blog/an-introduction-to-ngrams-in-elasticsearch

Searching for Shingles

https://www.elastic.co/blog/searching-with-shingles

https://codeslashslashcomment.com/2012/09/01/search-query-suggestions-using-elasticsearch-via-shingle-filter-and-facets/

https://www.elastic.co/guide/en/elasticsearch/reference/1.7/analysis-shingle-tokenfilter.html

http://stackoverflow.com/questions/23295896/shingles-in-elasticsearch-why-does-this-example-with-custom-analyzer-fail

https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-shingle-tokenfilter.html

https://www.elastic.co/guide/en/elasticsearch/guide/current/shingles.html

http://www.codegur.press/27410253/using-shingles-and-stop-words-with-elasticsearch-and-lucene-4-4

Видео

https://www.youtube.com/channel/UCUaTRF8LDgE6rQoduLWsErA/videos?nohtml5=False (ENG)

https://www.youtube.com/watch?v=otc_tRYnjmo Безопастность или способы взлома Elasticsearch из фронтенда (RUS)

https://www.youtube.com/watch?v=fe6kLv4UcVY (RUS)

https://www.youtube.com/watch?v=i6mTsTpOi2Y - на Ruby

https://www.youtube.com/watch?v=ARqtUizWkvg&list=PLlg3hnqqh7qEriIpdMSOLJzO5KhYffXua&nohtml5=False (ENG)

https://www.youtube.com/watch?v=Pse-2ZkVaTs&list=PLjQo0sojbbxWcy_byqkbe7j3boVTQurf9&nohtml5=False

https://vimeo.com/111068769 - Elasticsearch, Logstash, Kibana

https://www.youtube.com/watch?v=IsOkcielysE - Elasticsearch, Logstash

https://www.youtube.com/watch?v=gqV6FOvq7gk

https://www.youtube.com/watch?v=XCHYo0CsZrk

Презентации

http://www.slideshare.net/OmskIT/20130202-03-elasticsearch