Страницы

Поиск по вопросам

Показаны сообщения с ярлыком elasticsearch. Показать все сообщения
Показаны сообщения с ярлыком elasticsearch. Показать все сообщения

четверг, 13 февраля 2020 г.

Индексируется только часть файлов

#база_данных #elasticsearch #big_data


Необходимо проиндексировать большое количество (около 100к) файлов формата json разного
размера (на 100к файлов приходится в общем 1,2ГГб текстовой информации). 

Пишу на python, соответственно использую стандартный модуль для работы с Elasticsearch.
Из состава использую функцию helpers.bulk таким образом:

es = Elasticsearch(ES_CLUSTER)

json_docs = []
for filename in os.listdir(os.getcwd()):
    if filename.endswith('.json'):
        with open(filename) as open_file:
            json_docs.append(json.load(open_file))

helpers.bulk(ES_INDEX, ES_TYPE, json_docs)


В результате работы индексируется только 570 файлов. Причем заметил, что размер индекса
после каждого нового прогона программы сильно колеблется от 2-4мб до 15мб, хотя количество
проиндексированных файлов остается неизменным.

Размер индекса узнаю запросом:

curl 'localhost:9200/_cat/indices?v'


Очищаю так:

curl -XDELETE 'localhost:9200/_all/'


Видимо использую не оптимальный способ индексирования.
    


Ответы

Ответ 1



Очередь на индексацию в Elasticsearch по умолчанию ограничена.Вы пытаетесь скормить ему слишком много записей за раз. Это хоть и Bulk API, но работает он немного по другому: Необходимо отправлять порции в несколько сотен записей (подбирается экспериментально) es = Elasticsearch(ES_CLUSTER) json_docs = [] i=0 bulkSize=500 for filename in os.listdir(os.getcwd()): i++ if filename.endswith('.json'): with open(filename) as open_file: json_docs.append(json.load(open_file)) if len(json_docs) >= bulkSize: print(i, "current file:", datetime.now(), filename) try: helpers.bulk(ES_INDEX, ES_TYPE, json_docs) except Exception as error: print(error) del json_docs json_docs = [] //do not forget to put rest helpers.bulk(ES_INDEX, ES_TYPE, json_docs)

Ответ 2



Мы в своем проекте (не python) тоже индексируем большое кол-во информации. Основные моменты: Мы не индексируем через API - curl из bash Наш скрипт преобразует данные в формат bulk и кусками по 1000 документов складывает в обычный текстовый файл. После обработки всех данных запускаем консольный скрипт: files=(${1}*.txt) total=${#files[@]}; count=0 pstr="[=======================================================================]" echo "Start export to ElasticSearch ${total} files with data" for i in ${1}*.txt; do curl -XPOST http://elastic.domain.conm/_bulk --data-binary @${i} &>/dev/null count=$(( $count + 1 )) pd=$(( $count * 73 / $total )) printf "\r%3d.%1d%% %.${pd}s" $(( $count * 100 / $total )) $(( ($count * 1000 / $total) % 10 )) $pstr done printf "\n"

пятница, 24 января 2020 г.

Поиск текста с учетом звучания на русском и английском языках

#elasticsearch #индексация #полнотекстовый_поиск #lucene


Какими средствами лучше всего организовать индексирование и поиск русских слов, которые
являются записью английской транскрипции? Например, слово vision в русском варианте
будет записано как вижн или вижен, но значение сути не меняется. Поиск, соответственно,
должен быть произведен как по vision так и по вижн без потери результатов на выходе. 
Soundex и Metaphone, на сколько я понимаю, работают строго в одном языке без скрещиваний.
    


Ответы

Ответ 1



Мне кажется, в большинстве случаев, будет достаточно функционала синонимов. База данных, скорее всего, имеет определенную тематическую направленность, например медицина или электротехника. И чтобы настроить поиск с учетом транслита/звучания слов на разных языках достаточно заполнить 500-1000 синонимов. Но использовать анализатор с фильтром типа synonym не для индексации, а для анализа поискового запроса. Синонимы лучше вынести в отдельный файл, а не хранить в настройках. { "index" : { "analysis" : { "analyzer" : { "synonym" : { "tokenizer" : "whitespace", "filter" : ["synonym"] } }, "filter" : { "synonym" : { "type" : "synonym", "synonyms_path" : "analysis/synonym.txt" } } } } Пример содержимого файла synonym.txt: vision, вижн, вижен Если этого недостаточно, то получаем очень сложную задачу. Если дело ограничивается транслитом, то смотреть в сторону плагина ICU Transform Token Filter Если нет, и нужно vision, вижн, вижен для всех возможных слов, то смотреть в сторону машинного обучения. Это решение Rosette for Elasticsearch, видимо платное. Полезные ссылки. Обсуждение данной темы Rosette name translator - есть поддержка русского языка Soundex и Metaphone - это фонетические алгоритмы, работают, как вы написали, в одном языке. Это не то, что вам нужно.

вторник, 31 декабря 2019 г.

Неправильно работает поиск в Elasticsearch

#elasticsearch


Установил elastic. Настроил индексацию. Но в запросах какая-то странность выходит.
Никак не пойму почему поиск некорректно работает

Я делал запросы с помощью либы в ruby, и пенял на нее, однако когда отснифал запрос
понял что тут проблема в самом elastic. Да это даже не проблема, скорее фича. 

prod = Post.search "ра", fields: [:title] // На выходе n-элементов
prod = Post.search "разд", fields: [:title] // На выходе 0-элементов
prod = Post.search "раздел", fields: [:title] // На выходе n-элементов


Скорее всего где то надо найти настройку, которая позволит улучшить поиск. 
    


Ответы

Ответ 1



Скорее всего, это поведение анализатора. ES использует немного более сложную схему поиска, нежели привычное точное совпадение: При загрузке документа все текстовые поля пропускаются через анализатор, состоящий из токенайзера и фильтров Токенайзер бьет ввод на отдельные токены (как правило, это слова) Фильтры изменяют, добавляют и удаляют токены Токены записываются в конечный индекс При поиске запрос снова пропускается через анализатор, бьется на токены, и ES ищет совпадения между токенами запроса и токенами документа Я подозреваю, что проблема именно в этом - в ES существуют токены "ра" и "раздел", но не существует токена "разд". Скорее всего, дело именно в том, на какие токены разбивается запрос при поиске текущим анализатором. Чтобы проверить это, необходимо просмотреть токены совпадающих документов и токены запроса: curl -XGET :9200//_analyze -d '{ "text": "разд" }' curl -XGET :9200//_analyze -d '{ "text": "раздел" }' curl -XGET :9200//_analyze -d '{ "text": "<текст документа>" }' * В случае, если при поиске используется анализатор, отличный от анализатора индекса по умолчанию - скорее всего, вопрос это не подразумевает - его можно указать в поле "analyzer" * Токены документов можно получить напрямую из elasticsearch, но это немного сложнее Если вы использовали все настройки по умолчанию, то у вас стоит стандартный анализатор, который (во всяком случае, у меня) даст следующие результаты: Ра Разд Раздел (причем я смог добиться поиска по последним двум запросам, но даже при ненормально больших fuzziness ES отказася находить мне что-либо по "ра", что подталкивает к тому, что либо у вас все-таки нестандартный анализатор, либо я полностью забыл эластик) После этого вы можете посмотреть, как именно совпадает или не совпадает документ, с помощью explain API: curl -XGET :9200////_explain -d '{ "query": { "query_string" : { "query": "ра" } } }' * непосредственно запрос может отличаться и зависит от вашей библиотеки Таким образом вы сможете найти причину этого поведения самостоятельно - со стороны коммьюнити это почти невозможно, пока вы не привели mapping соответствующего индекса в ES, документы, которые совпадает по двум из трех запросов, непосредственно сам запрос, который передает библиотека и версию ES. Однако, насколько я понимаю, конкретно за этим вопросом стоит необходимость сделать автокомплит - в этом случае вам нужен не поиск внутри ES, а suggester completion - это немного другой функционал ES, который создан именно для реализации автокомплита.

среда, 25 декабря 2019 г.

Elasticsearch 5.1 подсветка результатов

#java #elasticsearch


Добрый день, 

Использую Elasticsearch 5.1 для хранения сущностей. 
Кто подскажет как сделать поиск и подсветку для всех полей?

    HighlightBuilder highlightBuilder = new HighlightBuilder()
            .postTags("")
            .preTags("")
            .highlightQuery(QueryBuilders.queryStringQuery( "ferrari"));


    SearchRequestBuilder request = client.prepareSearch("notemates")
            .setTypes("cars")
            .setQuery(QueryBuilders.queryStringQuery( "ferrari"))
            .setSearchType(SearchType.DEFAULT)
            .highlighter(highlightBuilder);
    SearchResponse response = request.get();


Подскажите где я не прав.
Спасибо
    


Ответы

Ответ 1



У себя делаю без дополнительного билдера. Вроде все работает... List highlightedFields = new ArrayList<>(); ... final SearchRequestBuilder builder = client.prepareSearch(filter.getIndexName()) .addSort(...) .setQuery(...) .setFrom(...) .setSize(...); ... for (String str : highlightedFields) { builder.addHighlightedField(str, 0, 0); }

вторник, 16 июля 2019 г.

Как ElasticSearch работает с БД?

На хосте произошел сбой, после этого сайт перестал работать, я востановил пару классов, которые были поврежденны, сайт заработал, но разделы где испльзуется ElasticSearch перестал работать, выходит такая ошибка:
CouldNotConnectToHost in AbstractConnection.php line 323: Failed to connect to 127.0.0.1 port 9200: Connection refused
Получается я немогу соединиться с БД, что бы отобразить страницу.
В логах на hhvm нашел такую строку:
Fatal error: Invalid operand type was used: cannot perform this operation with arrays in /home/uzbek/uzbek.rf/www/storage/framework/views/0822cd43cbe3e1a6fe6c9cbce47c072e on line 37
Что делать?


Ответ

ElasticSearch - это отдельный сервер, предназначенный для полнотекстового поиска. Судя по всему он просто не поднят после сбоя и сайт ожидает его ответов на локальном хосте по порту 9200. Убедиться в том запущен он или нет, можно при помощи команды
ps aux | grep elasticsearch

четверг, 11 июля 2019 г.

Elasticsearch получить ранжирование значение поля по уникальным записям

В Elasticsearch получить ранжирование значение поля по уникальным записям.
Индекс содержит записи о прыжках спортсменов. Попыток у одного спортсмена может быть множество.
Структура документа:
{ 'event_at' : '2015-01-01T12:12:10', - дата прыжка 'user_id' : 2142, - id спортсмена 'distance' : 4 - результат }
Необходимо получить выборку:
{ 'distance_range' : { '*-5' : 12, - кол-во уникальных спортсменов у которых максимальный прыжок от 0 до 5. '6-10' : 14, - кол-во уникальных спортсменов у которых максимальный прыжок от 6 до 10. '11-15' : 5 - кол-во уникальных спортсменов у которых максимальный прыжок от 10 до 15. } }
Пока у меня получалось только получить максимальный результат для каждого спортсмена, но я не могу понять как его можно ранжировать уровнем выше.
Для примера на SQL это могло бы выглядеть так:
SELECT `distace_range`, count(*) FROM ( SELECT `user_id`, IF(MAX(`distace`) <=5, '*-5', IF(MAX(`distace`) >= 6 AND MAX(`distace`) >= 10, '6-10', '11-15' ) ) `distace_range` FROM `events` GROUP BY `user_id` ) t GROUP BY `distace_range;


Ответ

Опубликовал вопрос на официальном форуме elasticsearch. На данный момент задачу такой выборки не решить штатными средствами для версии elasticsearch 2.1.х т.к. для запроса:
'aggregations' => [ 'distance_range' => [ 'terms' => [ 'field' => 'doc.user_id',
], 'aggregations' => [ 'max_distance' => [ 'max' => [ 'field' => 'doc.distance' ] ] ] ] ]
то не хватает Pipeline агрегатора по range или term
Есть несколько подходов для решения в текущей ситуации:
создание дополнительного индекса содержащего максимальный результат использование скриптов просуммировать результат на клиенте
В данный момент я воспользовался 3 вариантом.
Вариант 1 меня не устроил тем, что дополнительный индекс необходимо контролировать, что-бы он был актуален.
Вариант 2 сложность вычисления или влияние на выборку очень сильно влияет на время выборки и дополнительно придется поддерживать код в нескольких системах.

понедельник, 18 марта 2019 г.

Поиск текста с учетом звучания на русском и английском языках

Какими средствами лучше всего организовать индексирование и поиск русских слов, которые являются записью английской транскрипции? Например, слово vision в русском варианте будет записано как вижн или вижен, но значение сути не меняется. Поиск, соответственно, должен быть произведен как по vision так и по вижн без потери результатов на выходе. Soundex и Metaphone, на сколько я понимаю, работают строго в одном языке без скрещиваний.


Ответ

Мне кажется, в большинстве случаев, будет достаточно функционала синонимов. База данных, скорее всего, имеет определенную тематическую направленность, например медицина или электротехника. И чтобы настроить поиск с учетом транслита/звучания слов на разных языках достаточно заполнить 500-1000 синонимов. Но использовать анализатор с фильтром типа synonym не для индексации, а для анализа поискового запроса.
Синонимы лучше вынести в отдельный файл, а не хранить в настройках.
{ "index" : { "analysis" : { "analyzer" : { "synonym" : { "tokenizer" : "whitespace", "filter" : ["synonym"] } }, "filter" : { "synonym" : { "type" : "synonym", "synonyms_path" : "analysis/synonym.txt" } } } }

Пример содержимого файла synonym.txt:
vision, вижн, вижен

Если этого недостаточно, то получаем очень сложную задачу.
Если дело ограничивается транслитом, то смотреть в сторону плагина ICU Transform Token Filter Если нет, и нужно vision, вижн, вижен для всех возможных слов, то смотреть в сторону машинного обучения. Это решение Rosette for Elasticsearch, видимо платное.
Полезные ссылки.
Обсуждение данной темы Rosette name translator - есть поддержка русского языка
Soundex и Metaphone - это фонетические алгоритмы, работают, как вы написали, в одном языке. Это не то, что вам нужно.

понедельник, 17 декабря 2018 г.

Неправильно работает поиск в Elasticsearch

Установил elastic. Настроил индексацию. Но в запросах какая-то странность выходит. Никак не пойму почему поиск некорректно работает
Я делал запросы с помощью либы в ruby, и пенял на нее, однако когда отснифал запрос понял что тут проблема в самом elastic. Да это даже не проблема, скорее фича.
prod = Post.search "ра", fields: [:title] // На выходе n-элементов prod = Post.search "разд", fields: [:title] // На выходе 0-элементов prod = Post.search "раздел", fields: [:title] // На выходе n-элементов
Скорее всего где то надо найти настройку, которая позволит улучшить поиск.


Ответ

Скорее всего, это поведение анализатора. ES использует немного более сложную схему поиска, нежели привычное точное совпадение:
При загрузке документа все текстовые поля пропускаются через анализатор, состоящий из токенайзера и фильтров Токенайзер бьет ввод на отдельные токены (как правило, это слова) Фильтры изменяют, добавляют и удаляют токены Токены записываются в конечный индекс При поиске запрос снова пропускается через анализатор, бьется на токены, и ES ищет совпадения между токенами запроса и токенами документа
Я подозреваю, что проблема именно в этом - в ES существуют токены "ра" и "раздел", но не существует токена "разд".
Скорее всего, дело именно в том, на какие токены разбивается запрос при поиске текущим анализатором. Чтобы проверить это, необходимо просмотреть токены совпадающих документов и токены запроса:
curl -XGET :9200//_analyze -d '{ "text": "разд" }'
curl -XGET :9200//_analyze -d '{ "text": "раздел" }'
curl -XGET :9200//_analyze -d '{ "text": "<текст документа>" }'
* В случае, если при поиске используется анализатор, отличный от анализатора индекса по умолчанию - скорее всего, вопрос это не подразумевает - его можно указать в поле "analyzer" * Токены документов можно получить напрямую из elasticsearch, но это немного сложнее
Если вы использовали все настройки по умолчанию, то у вас стоит стандартный анализатор, который (во всяком случае, у меня) даст следующие результаты:
Ра Разд Раздел
(причем я смог добиться поиска по последним двум запросам, но даже при ненормально больших fuzziness ES отказася находить мне что-либо по "ра", что подталкивает к тому, что либо у вас все-таки нестандартный анализатор, либо я полностью забыл эластик)
После этого вы можете посмотреть, как именно совпадает или не совпадает документ, с помощью explain API:
curl -XGET :9200////_explain -d '{ "query": { "query_string" : { "query": "ра" } } }'
* непосредственно запрос может отличаться и зависит от вашей библиотеки
Таким образом вы сможете найти причину этого поведения самостоятельно - со стороны коммьюнити это почти невозможно, пока вы не привели mapping соответствующего индекса в ES, документы, которые совпадает по двум из трех запросов, непосредственно сам запрос, который передает библиотека и версию ES. Однако, насколько я понимаю, конкретно за этим вопросом стоит необходимость сделать автокомплит - в этом случае вам нужен не поиск внутри ES, а suggester completion - это немного другой функционал ES, который создан именно для реализации автокомплита.