Статьи

Создайте поисковую систему с Node.js и Elasticsearch

Эта статья была рецензирована Марком Брауном , Вилданом Софтиком и Морицем Крегером . Спасибо всем рецензентам SitePoint за то, что сделали контент SitePoint как можно лучше!

Elasticsearch — это поисковая система с открытым исходным кодом, которая набирает популярность благодаря своей высокой производительности и распределенной архитектуре. В этой статье я расскажу о его основных функциях и проведу вас через процесс его использования для создания поисковой системы Node.js.

Введение в Elasticsearch

Elasticsearch построен на основе Apache Lucene , который является высокопроизводительной библиотекой текстового поискового движка. Хотя Elasticsearch может выполнять хранение и извлечение данных, его основная цель не состоит в том, чтобы служить базой данных, скорее это поисковая система (сервер) с основной целью индексации, поиска и предоставления статистики данных в реальном времени.

Elasticsearch имеет распределенную архитектуру, которая позволяет горизонтальное масштабирование, добавляя больше узлов и используя преимущества дополнительного оборудования. Он поддерживает тысячи узлов для обработки петабайт данных. Горизонтальное масштабирование также означает, что он имеет высокую доступность за счет перебалансировки данных, если когда-либо отказывают какие-либо узлы.

Когда данные импортируются, они сразу становятся доступными для поиска. Elasticsearch не имеет схемы, хранит данные в документах JSON и может автоматически определять структуру и тип данных.

Elasticsearch также полностью управляется API. Это означает, что практически любые операции могут быть выполнены с помощью простого RESTful API с использованием данных JSON через HTTP. Он имеет много клиентских библиотек практически для любого языка программирования, в том числе для Node.js. В этом уроке мы будем использовать официальную клиентскую библиотеку .

Elasticsearch очень гибок в отношении требований к аппаратному и программному обеспечению. Несмотря на то, что рекомендуется использовать 64 ГБ памяти и максимально возможное количество ядер ЦП, вы все равно можете запустить его в системе с ограниченными ресурсами и получить приличную производительность (при условии, что ваш набор данных невелик). Для следования примерам, приведенным в этой статье, достаточно системы с 2 ГБ памяти и одним ядром ЦП.

Вы можете запустить Elasticsearch на всех основных операционных системах (Linux, Mac OS и Windows). Для этого вам нужно установить последнюю версию Java Runtime Environment (см. Раздел « Установка Elasticsearch »). Чтобы следовать примерам из этой статьи, вам также нужно установить Node.js (подойдет любая версия после v0.11.0), а также npm .

Elasticsearch терминология

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

Индекс : этот термин имеет два значения в контексте Elasticsearch. Сначала идет операция добавления данных. Когда данные добавляются, текст разбивается на токены (например, слова), и каждый токен индексируется. Однако индекс также указывает, где хранятся все проиндексированные данные. В основном, когда вы импортируете данные, они индексируются в индекс. Каждый раз, когда вы хотите выполнить какую-либо операцию с данными, вам нужно указать ее индексное имя.

Тип : Elasticsearch обеспечивает более подробную категоризацию документов в индексе, который называется типом. Каждый документ в индексе также должен иметь тип. Например, мы можем определить library индекс, а затем индексировать в него несколько типов данных, таких как article , book , report и presentation . Поскольку индексы имеют почти фиксированные накладные расходы, рекомендуется иметь меньше индексов и больше типов, а не больше индексов и меньше типов.

Поиск : этот термин означает, что вы можете подумать. Вы можете искать данные в различных индексах и типах. Elasticsearch предоставляет много типов поисковых запросов, таких как термин, фраза, диапазон, нечеткие и даже запросы для геоданных.

Фильтр : Elasticsearch позволяет фильтровать результаты поиска по различным критериям, чтобы еще больше сузить результаты. Если вы добавите новые поисковые запросы в набор документов, это может изменить порядок в зависимости от релевантности, но если вы добавите тот же запрос, что и фильтр, порядок останется неизменным.

Агрегации . Они предоставляют вам различные типы статистики для агрегированных данных, такие как минимум, максимум, среднее, суммирование, гистограммы и т. Д.

Предложения : Elasticsearch предоставляет различные типы предложений для ввода текста. Эти предложения могут быть основаны на термине или фразе, или даже дополнения.

Установка Elasticsearch

Elasticsearch доступен под лицензией Apache 2; он может быть загружен, использован и изменен бесплатно. Перед установкой убедитесь, что на вашем компьютере установлена ​​Java Runtime Environment (JRE). Elasticsearch написан на Java и использует библиотеки Java для запуска. Чтобы проверить, установлена ​​ли в вашей системе Java, вы можете ввести в командной строке следующее.

 java -version 

Рекомендуется использовать последнюю стабильную версию Java (1.8 на момент написания этой статьи). Вы можете найти руководство по установке Java в вашей системе здесь .

Затем, чтобы загрузить последнюю версию Elasticsearch (2.4.0 на момент написания этой статьи), перейдите на страницу загрузки и загрузите ZIP-файл. Elasticsearch не требует установки, а один zip-файл содержит полный набор файлов для запуска программы во всех поддерживаемых операционных системах. Распакуйте загруженный файл и все готово! Есть несколько других способов запустить Elasticsearch, например, получить файл TAR или пакеты для разных дистрибутивов Linux (смотрите здесь ).

Если вы используете Mac OS X и у вас установлен Homebrew , вы можете установить Elasticsearch с помощью brew install elasticsearch . Homebrew автоматически добавляет исполняемые файлы на ваш путь и устанавливает необходимые сервисы. Это также поможет вам обновить приложение с помощью одной команды: brew upgrade elasticsearch .

Чтобы запустить Elasticsearch в Windows, из разархивированного каталога запустите bin\elasticsearch.bat из командной строки. Для любой другой ОС запустите ./bin/elasticsearch из терминала. На этом этапе он должен быть запущен в вашей системе.

Как я упоминал ранее, почти все операции, которые вы можете выполнять с Elasticsearch, могут выполняться через API RESTful. Elasticsearch использует порт 9200 по умолчанию. Чтобы убедиться, что вы используете его правильно, перейдите по http://localhost:9200/ в вашем браузере, и он должен отобразить некоторую основную информацию о вашем запущенном экземпляре.

Для получения дополнительной информации об установке и устранении неполадок, вы можете посетить документацию .

Графический интерфейс пользователя

Elasticsearch обеспечивает почти всю свою функциональность через API REST и не поставляется с графическим интерфейсом пользователя (GUI). Хотя я расскажу о том, как вы можете выполнять все необходимые операции через API и Node.js, есть несколько инструментов с графическим интерфейсом, которые предоставляют визуальную информацию об индексах и данных, и даже некоторые аналитики высокого уровня.

Kibana , разработанная той же компанией, предоставляет в реальном времени сводку данных, а также несколько настраиваемых параметров визуализации и аналитики. Kibana бесплатна и имеет подробную документацию .

Сообщество разработало и другие инструменты, в том числе Elasticsearch , Elasticsearch GUI и даже расширение Chrome под названием ElasticSearch Toolbox . Эти инструменты помогут вам изучить ваши индексы и данные в браузере и даже попробовать различные поисковые и агрегирующие запросы. Все эти инструменты обеспечивают пошаговое руководство по установке и использованию.

Настройка среды Node.js

Elasticsearch предоставляет официальный модуль для Node.js, который называетсяasticsearch. Во-первых, вам нужно добавить модуль в папку вашего проекта и сохранить зависимость для дальнейшего использования.

 npm install elasticsearch --save 

Затем вы можете импортировать модуль в свой скрипт следующим образом:

 const elasticsearch = require('elasticsearch'); 

Наконец, вам нужно настроить клиент, который обрабатывает связь с Elasticsearch. В этом случае я предполагаю, что вы запускаете Elasticsearch на локальном компьютере с IP-адресом 127.0.0.1 и портом 9200 (настройка по умолчанию).

 const esClient = new elasticsearch.Client({ host: '127.0.0.1:9200', log: 'error' }); 

Параметры log гарантируют, что все ошибки будут зарегистрированы. В оставшейся части этой статьи я буду использовать тот же объект esClient для связи с Elasticsearch. Полная документация для модуля узла приведена здесь .

Примечание : весь исходный код этого руководства предоставляется на GitHub . Самый простой способ — скопировать репозиторий на ваш компьютер и запустить примеры оттуда:

 git clone https://github.com:sitepoint-editors/node-elasticsearch-tutorial.git cd node-elasticsearch-tutorial npm install 

Импорт данных

В этом уроке я буду использовать набор академических статей со случайно сгенерированным контентом. Данные предоставляются в формате JSON, и в наборе данных содержится 1000 статей. Чтобы показать, как выглядят данные, ниже показан один элемент из набора данных.

 { "_id": "57508457f482c3a68c0a8ab3", "title": "Nostrud anim proident cillum non.", "journal": "qui ea", "volume": 54, "number": 11, "pages": "109-117", "year": 2014, "authors": [ { "firstname": "Allyson", "lastname": "Ellison", "institution": "Ronbert", "email": "[email protected]" }, ... ], "abstract": "Do occaecat reprehenderit dolore ...", "link": "http://mollit.us/57508457f482c3a68c0a8ab3.pdf", "keywords": [ "sunt", "fugiat", ... ], "body": "removed to save space" } 

Имена полей говорят сами за себя. Единственное, на что следует обратить внимание, это то, что поле body здесь не отображается, поскольку оно содержит полную, случайно сгенерированную статью (от 100 до 200 абзацев). Вы можете найти полный набор данных здесь .

В то время как Elasticsearch предоставляет методы для индексирования , обновления и удаления отдельных точек данных, мы собираемся использовать массовый метод Elasticserch для импорта данных, который используется для более эффективного выполнения операций с большими наборами данных:

 // index.js const bulkIndex = function bulkIndex(index, type, data) { let bulkBody = []; data.forEach(item => { bulkBody.push({ index: { _index: index, _type: type, _id: item.id } }); bulkBody.push(item); }); esClient.bulk({body: bulkBody}) .then(response => { console.log('here'); let errorCount = 0; response.items.forEach(item => { if (item.index && item.index.error) { console.log(++errorCount, item.index.error); } }); console.log( `Successfully indexed ${data.length - errorCount} out of ${data.length} items` ); }) .catch(console.err); }; const test = function test() { const articlesRaw = fs.readFileSync('data.json'); bulkIndex('library', 'article', articles); }; 

Здесь мы вызываем функцию bulkIndex передавая ей library качестве имени индекса, article в качестве типа и данные JSON, которые мы хотим проиндексировать. Функция bulkIndex в свою очередь, вызывает метод esClient объекта esClient . Этот метод принимает объект со свойством body в качестве аргумента. Значение, предоставленное свойству body представляет собой массив с двумя записями для каждой операции. В первой записи тип операции указан как объект JSON. Внутри этого объекта свойство index определяет выполняемую операцию (в данном случае индексирование документа), а также имя индекса, имя типа и идентификатор документа. Следующая запись соответствует самому документу.

Обратите внимание, что в будущем вы можете добавить другие типы документов (например, книги или отчеты) в этот же индекс. Мы также можем назначить уникальный идентификатор каждому документу, но это необязательно — если вы его не предоставите, Elasticsearch назначит уникальный случайно сгенерированный идентификатор каждому документу для вас.

Предполагая, что вы клонировали репозиторий, теперь вы можете импортировать данные в Elasticsearch, выполнив следующую команду из корня проекта:

 $ node index.js 1000 items parsed from data file Successfully indexed 1000 out of 1000 items 

Проверка правильности индексации данных

Одна из замечательных особенностей Elasticsearch — поиск в режиме реального времени. Это означает, что как только документы проиндексированы, они становятся доступными для поиска в течение одной секунды (см. Здесь ). Как только данные проиндексированы, вы можете проверить информацию об индексе, запустив indices.js ( ссылка на источник ):

 // indices.js const indices = function indices() { return esClient.cat.indices({v: true}) .then(console.log) .catch(err => console.error(`Error connecting to the es client: ${err}`)); }; 

Методы в клиентском объекте cat предоставляют различную информацию о текущем запущенном экземпляре. Метод indices перечисляет все индексы, их состояние здоровья, количество их документов и их размер на диске. Опция v добавляет заголовок к ответу от методов cat .

Когда вы запустите приведенный выше фрагмент, вы заметите, что он выводит цветовой код, указывающий состояние вашего кластера. Красный указывает, что что-то не так с вашим кластером, и он не работает. Желтый означает, что кластер работает, но есть предупреждение, а зеленый означает, что все работает нормально. Скорее всего (в зависимости от ваших настроек) вы получите желтый статус при работе на локальном компьютере. Это связано с тем, что настройки по умолчанию содержат пять узлов для кластера, но на вашем локальном компьютере работает только один экземпляр. Хотя вы всегда должны стремиться к зеленому статусу в производственной среде, для целей данного руководства вы можете продолжать использовать Elasticsearch в желтом статусе.

 $ node indices.js elasticsearch indices information: health status index pri rep docs.count docs.deleted store.size pri.store.size yellow open library 5 1 1000 0 41.2mb 41.2mb 

Динамическое и пользовательское отображение

Как я упоминал ранее, Elasticsearch не содержит схем. Это означает, что вам не нужно определять структуру ваших данных (аналогично определению таблицы в базе данных SQL), прежде чем импортировать ее, скорее Elasticsearch автоматически обнаружит ее для вас. Но, несмотря на то, что он называется без схемы, существуют некоторые ограничения в структуре данных.

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

Например, если {"key1": 12} уже проиндексирован, Elasticsearch автоматически отображает поле key1 как long . Теперь, если вы попытаетесь проиндексировать {"key1": "value1", "key2": "value2"} , он выдаст ошибку, ожидающую, что тип поля key1 будет long . В то же время объект {"key1": 13, "key2": "value2"} будет проиндексирован без каких-либо проблем, при этом к отображению добавится key2 типа string .

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

Создание поисковой системы

Как только данные были проиндексированы, мы готовы внедрить поисковую систему. Elasticsearch предоставляет интуитивно понятную структуру полного поискового запроса под названием Query DSL, которая основана на JSON, для определения запросов. Существует много типов поисковых запросов, но в этой статье мы рассмотрим некоторые из наиболее распространенных. Полную документацию по Query DSL можно найти здесь .

Пожалуйста, помните, что я предоставляю ссылку на код за каждым показанным примером. После настройки среды и индексации тестовых данных вы можете клонировать репозиторий и запустить любой из примеров на своем компьютере. Для этого просто запустите node filename.js из командной строки.

Вернуть все документы в одном или нескольких индексах

Для выполнения нашего поиска мы будем использовать различные методы поиска, предоставляемые клиентом. Самый простой запрос — match_all , который возвращает все документы в одном или нескольких индексах. Пример ниже показывает, как мы можем получить все сохраненные документы в индексе ( ссылка на источник ).

 //search_all.js const search = function search(index, body) { return esClient.search({index: index, body: body}); }; const test = function test() { let body = { size: 20, from: 0, query: { match_all: {} } }; search('library', body) .then(results => { console.log(`found ${results.hits.total} items in ${results.took}ms`); console.log(`returned article titles:`); results.hits.hits.forEach( (hit, index) => console.log( `\t${body.from + ++index} - ${hit._source.title}` ) ) }) .catch(console.error); }; 

Основной поисковый запрос включен в объект query . Как мы увидим позже, мы можем добавить различные типы поисковых запросов к этому объекту. Для каждого запроса мы добавляем ключ с типом запроса (в этом примере match_all ) со значением, являющимся объектом, содержащим параметры поиска. В этом примере нет опций, так как мы хотим вернуть все документы в индексе.

В дополнение к объекту query тело поиска может содержать другие необязательные свойства, в том числе size и from . Свойство size определяет количество документов, которые будут включены в ответ. Если это значение отсутствует, по умолчанию возвращается десять документов. Свойство from определяет начальный индекс возвращаемых документов. Это полезно для нумерации страниц.

Понимание ответа API поиска

Если вы выйдете из ответа от API поиска ( results в приведенном выше примере), он может сначала выглядеть подавляющим, поскольку содержит много информации.

 { took: 6, timed_out: false, _shards: { total: 5, successful: 5, failed: 0 }, hits: { total: 1000, max_score: 1, hits: [ [Object], [Object], ... [Object] ] } } 

На самом высоком уровне ответ включает в took свойство timed_out для количества времени, которое потребовалось для поиска результатов, timed_out , который имеет значение true только если в течение максимально допустимого времени не было найдено результатов, _shards для информации о состоянии различных узлов. (если развернуто как кластер узлов), и hits , которые включают результаты поиска.

В пределах свойства hits у нас есть следующие свойства:

  • total — указывает общее количество подходящих элементов
  • max_score — максимальная оценка найденных предметов
  • hits — массив, который включает в себя найденные элементы. Внутри каждого документа в массиве _source у нас есть индекс, тип, идентификатор документа, оценка и сам документ (внутри элемента _source ).

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

Также обратите внимание, что одним из преимуществ Elasticsearch является то, что он автоматически присваивает оценку каждому сопоставленному документу. Эта оценка используется для количественной оценки релевантности документа, а результаты возвращаются в порядке убывания по умолчанию. В случае, когда мы извлекаем все документы с помощью match_all , оценка не имеет смысла, и все оценки рассчитываются как 1,0.

Соответствие документов, которые содержат определенные значения в поле

Теперь давайте посмотрим на еще несколько интересных примеров. Для сопоставления документов, которые содержат определенные значения в поле, мы можем использовать запрос match . Простое тело поиска с запросом на match показано ниже ( ссылка на источник ).

 // search_match.js { query: { match: { title: { query: 'search terms go here' } } } } 

Как я упоминал ранее, мы сначала добавляем запись в объект запроса с типом поиска, который match в приведенном выше примере. Внутри объекта типа поиска мы идентифицируем поле документа для поиска, которое здесь является title . Внутри этого мы помещаем связанные с поиском данные, включая свойство query . Я надеюсь, что после тестирования приведенного выше примера, вы начинаете удивляться скорости поиска.

Приведенный выше поисковый запрос возвращает документы, чье поле заголовка соответствует любым словам в свойстве query . Мы можем установить минимальное количество подходящих терминов следующим образом.

 // search_match.js ... match: { title: { query: 'search terms go here', minimum_should_match: 3 } } ... 

Этот запрос сопоставляет документы, в заголовке которых указано не менее трех указанных слов. Если в запросе меньше трех слов, в заголовке должны присутствовать все слова для сопоставления документа. Еще одна полезная функция для добавления к поисковым запросам — нечеткость. Это полезно, если пользователь делает опечатку при написании запроса, так как при нечетком сопоставлении будут найдены термины, написанные тесно. Для строк значение нечеткости основано на максимально допустимом расстоянии Левенштейна для каждого члена. Ниже приведен пример с нечеткостью.

 match: { title: { query: 'search tems go here', minimum_should_match: 3, fuzziness: 2 } } 

Поиск в нескольких полях

Если вы хотите искать в нескольких полях, можно использовать тип поиска multi_match . Это похоже на match , за исключением того, что вместо поля в качестве ключа в объекте поискового запроса мы добавляем ключ fields , который представляет собой массив полей для поиска. Здесь мы ищем в полях title , authors.firstname и authors.lastname . ( ссылка на источник )

 // search_multi_match multi_match: { query: 'search terms go here', fields: ['title', 'authors.firstname', 'authors.lastname'] } 

Запрос multi_match поддерживает другие поисковые свойства, такие как minimum_should_match и minimum_should_match . Elasticsearch поддерживает подстановочные знаки (например, * ) для сопоставления нескольких полей, поэтому мы можем сократить приведенный выше пример до ['title', 'authors.*name'] .

Соответствие полной фразе

Elasticsearch также может соответствовать фразе в точности как введено, без сопоставления на уровне термина. Этот запрос является расширением обычного запроса на match , который называется match_phrase . Ниже приведен пример match_phrase . ( ссылка на источник )

 // match_phrase.js match: { title: { query: 'search phrase goes here', type: 'phrase' } } 

Объединение нескольких запросов

До сих пор в примерах мы использовали только один запрос на запрос. Elasticsearch, однако, позволяет объединять несколько запросов. Самым распространенным сложным запросом является bool . Запрос bool принимает четыре типа ключей: must , must , must_not и filter . Как следует из их имен, документы в результатах должны соответствовать запросам в must , не должны совпадать с запросами в must_not , и получат более высокий балл, если они будут соответствовать запросам в must_not . Каждый из упомянутых элементов может получать несколько поисковых запросов в виде массива запросов.

Ниже мы используем запрос bool вместе с новым типом запроса под названием query_string . Это позволяет вам писать более сложные запросы, используя ключевые слова, такие как AND и OR . Полная документация по синтаксису query_string может быть найдена здесь . Кроме того, мы используем запрос range (документация здесь ), который позволяет нам ограничить поле заданным диапазоном. (ссылка на источник )

 // search_bool.js { bool: { must: [ { query_string: { query: '(authors.firstname:term1 OR authors.lastname:term2) AND (title:term3)' } } ], should: [ { match: { body: { query: 'search phrase goes here', type: 'phrase' } } } ], must_not: [ { range: { year: { gte: 2011, lte: 2013 } } } ] } } 

В приведенном выше примере запрос возвращает документы, в которых имя автора содержит term1 или их фамилия содержит term2 , а их заголовок имеет term3 , и они не были опубликованы в 2011, 2012 или 2013 годах. Кроме того, документы, имеющие фразы в их body , получают более высокие оценки и отображаются в верхней части результатов (так как запрос на match находится в предложении must).

Фильтры, агрегаты и предложения

В дополнение к расширенным возможностям поиска Elasticsearch предоставляет и другие функциональные возможности. Здесь мы рассмотрим три наиболее общих черты.

фильтры

Часто вы можете захотеть уточнить результаты поиска на основе определенных критериев. Elasticsearch предоставляет эту функциональность через фильтры. В наших данных статей, представьте, что ваш поиск дал несколько статей, из которых вы хотите выбрать только те статьи, которые были опубликованы за пять лет. Вы можете просто отфильтровать все, что не соответствует вашим критериям из результатов поиска, без изменения порядка поиска.

Различие между фильтром и тем же запросом в условии must запроса bool состоит в том, что фильтр не влияет на результаты поиска, в то время как запросы must это делать. Когда результаты поиска возвращаются и пользователь выполняет фильтрацию по некоторым конкретным критериям, они не хотят, чтобы исходный порядок результатов был изменен, вместо этого они хотят только удалить ненужные документы из результатов. Фильтры следуют тому же формату, что и поиск, но чаще они определяются в полях с определенными значениями, а не в строках текста. Elasticsearch рекомендует добавлять фильтры через предложение filter поискового запроса соединения bool .

Следуя приведенному выше примеру, представьте, что мы хотим ограничить результаты нашего поиска статьями, опубликованными в период с 2011 по 2015 годы. Для этого нам нужно только добавить запрос range в раздел filter исходного поискового запроса. Это удалит все несопоставимые документы из результатов. Ниже приведен пример фильтрованного запроса. (ссылка на источник )

 // filter.js { bool: { must: [ { match: { title: 'search terms go here' } } ], filter: [ { range: { year: { gte: 2011, lte: 2015 } } } ] } } 

Скопления

Структура агрегации предоставляет различные агрегированные данные и статистику на основе поискового запроса. Два основных типа агрегации — это метрика и группировка, где агрегация метрик отслеживает и вычисляет метрики по набору документов, а агрегация по группам строит сегменты, причем каждый сегмент связан с ключом и критерием документа. Примерами агрегирования метрик являются среднее, минимальное, максимальное, суммирование и подсчет значений. Примерами группируемых агрегатов являются диапазон, диапазон дат, гистограмма и термины. Подробное объяснение агрегаторов можно найти здесь .

Агрегации размещаются внутри объекта aggregations , который сам размещается непосредственно в теле search объекта. В объекте aggregations каждый ключ является именем, назначенным агрегатору пользователем. Тип агрегатора и опции должны быть помещены в качестве значения для этого ключа. Ниже мы рассмотрим два разных агрегатора, один показатель и один сегмент. В качестве агрегатора метрик мы пытаемся найти минимальное значение года в нашем наборе данных (самая старая статья), а для агрегатора сегментов мы пытаемся определить, сколько раз появлялось каждое ключевое слово. (ссылка на источник )

 // aggregations.js { aggregations: { min_year: { min: {field: 'year'} }, keywords: { terms: {field: 'keywords'} } } } 

В приведенном выше примере мы назвали метрический агрегатор min_year (это имя может быть любым), который имеет тип min в поле field year . Агрегатор сегментов именуется keywords , который имеет типовые terms по keywords поля. Результаты агрегации заключены в элементе aggregations в ответе, и на более глубоком уровне они содержат каждый определенный агрегатор ( min_year и keywords здесь) вместе с его результатами. Ниже приведен частичный ответ из этого примера.

 { ... "aggregations": { "keywords": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 2452, "buckets": [ { "key": "pariatur", "doc_count": 88 }, { "key": "adipisicing", "doc_count": 75 }, ... ] }, "min_year": { "value": 1970 } } } 

По умолчанию в ответ возвращается не более 10 сегментов. Вы можете добавить ключ size рядом с field в запросе, чтобы определить максимальное количество возвращаемых сегментов. Если вы хотите получить все сегменты, установите это значение равным 0.

Предложения

Elasticsearch имеет несколько типов подсказок, которые предоставляют предложения замены или дополнения для введенных условий (документация здесь ). Мы посмотрим на предлагаемые термины и фразы здесь. Подсказчик термина предлагает предложения (если таковые имеются) для каждого термина во введенном тексте, тогда как подсказчик фразы рассматривает введенный текст как целую фразу (в отличие от разбивки его на термины) и предоставляет другие предложения фразы (если таковые имеются). Чтобы использовать API подсказок, нам нужно вызвать метод подсказки на клиенте Node.js. Ниже приведен пример термина предложения. (ссылка на источник )

 // suggest_term.js esClient.suggest({ index: 'articles', body: { text: 'text goes here', titleSuggester: { term: { field: 'title', size: 5 } } } }).then(...) 

В теле запроса, совместимом со всеми другими методами клиента, у нас есть поле index определяющее индекс для поиска. В свойстве body мы добавляем текст, для которого мы ищем предложения, и (как и в случае объектов агрегации) мы даем каждому предложителю имя (в данном случае titleSuggester ). Его значение определяет тип и параметры подсказки. В этом случае мы используем term предложение» для поля title и ограничиваем максимальное количество предложений на один токен пятью ( size: 5 ).

Ответ от API подсказки содержит один ключ для каждого запрошенного вами подсказчика, который представляет собой массив того же размера, что и число терминов в text поле. Для каждого объекта в этом массиве есть объект options содержащий предложения в его text поле. Ниже приведена часть ответа на вышеуказанный запрос.

 ... "titleSuggester": [ { "text": "term", "offset": 0, "length": 4, "options": [ { "text": "terms", "score": 0.75, "freq": 120 }, { "text": "team", "score": 0.5, "freq": 151 } ] }, ... ] ... 

Чтобы получить предложения фразы, мы можем использовать тот же формат, что и выше, и просто заменить тип подсказки на phrase . В следующем примере ответ следует в том же формате, что и поясненный выше. (ссылка на источник )

 // suggest_phrase.js esClient.suggest({ index: 'articles', body: { text: 'phrase goes here', bodySuggester: { phrase: { field: 'body' } } } }).then(...).catch(...); 

Дальнейшее чтение

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

После ознакомления с примерами, приведенными здесь, я настоятельно рекомендую ознакомиться с документацией. Они предоставляют два основных источника, один из которых представляет собой ссылку на Elasticsearch и его функции , а другой — руководство, в котором больше внимания уделяется реализации, вариантам использования и передовым методам. Вы также можете найти подробную документацию по клиенту Node.js здесь .

Вы уже используете Elasticsearch? Каковы ваши переживания? Или, может быть, вы собираетесь попробовать после прочтения этой статьи. Позвольте мне знать в комментариях ниже.