Статьи

Мой опыт с использованием ElasticSearch NodeJS и ExpressJS

Общее требование

Частью системы, над которой я сейчас работаю, является обработка необработанных данных. Данные, отправляемые с нескольких клиентских устройств (устройств Android / Iphone и т. Д.) ~ 100 000 запросов в день
Необработанные данные должны быть собраны и готовы для последующего использования. Он должен быть доступен для поиска и агрегировать для расчетов.

У меня было мало опыта с Solr, но на этот раз я хотел попробовать ElasticSearch (ES). Я прочитал об ES из кластера и возможностей шардов, поэтому я попробовал.

ES

Установка проста и быстра. ES поставляется с удобной панелью пользовательского интерфейса (Marvel) и инструментом командной строки для выполнения запросов.

После игры с фреймворком я создал свои первые типы Index и Mapping (MyIndex, MyType).

В тот момент я не знал, как именно будут структурированы мои данные, поэтому я пошел в «запрос всех полей». Это означает, что при поиске одного входа механизм ES будет проходить через все документы и искать в поле каждого документа. Соответствующие документы вернутся.

Мы можем достичь этого, используя поле _all. Это поле включает в себя сглаженный текст одного или нескольких других полей в индексируемом документе. Поле заполняется по умолчанию (если включено).

Запрос довольно прост:

1
2
3
4
5
6
GET /_search
{
    "match": {
        "_all": "Android Galaxy S5 device"
    }
}

Панель инструментов ES также поставляется с инструментом под названием Sense. С помощью этого инструмента вы можете индексировать и выполнять запросы прямо в ES без использования клиента (это хорошо для тестирования и разработки).

Я предлагаю вам бросить отображение, анализ, повышение, псевдонимы и т.д …

NodeJS

Поэтому после игры с ES я решил написать слой на стороне сервера, который будет моим фасадом ES.

Я намеревался написать простой клиент с единственной строкой поиска, который будет отправлять запросы к ES через уровень сервера и отображать результаты на экране.

ES работает с Json в качестве входа и выхода. Я подумал об использовании JavaScript, который работает комфортно с JSON.

Nodejs — это уровень на стороне сервера, также использующий синтаксис JS. Вот почему JavaScript делает Node идеальным языком для взаимодействия с ElasticSearch. Копать это?

Я взял реализацию клиента ES (asticsearchclient) для NodeJS и после кодирования завершил интеграцию между узлом и ES. Вот пример кода со стороны узла для запроса ES:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
var index = "myindex";
var type = "mytype";
ElasticSearchClient = require('elasticsearchclient');
var Q = require('q');
 
 
var serverOptions = {
    host: 'localhost',
    port: 9200
};
 
var elasticSearchClient = new ElasticSearchClient(serverOptions);
 
function performSearch(termToSearch) {
 
    var deferred = Q.defer();
    console.log("Request handler 'search' was called.");
    var qryObj = {
        "query" : {
            "term" : { "name":termToSearch }
        }
    };
    elasticSearchClient.search(index, type, qryObj).
        on('data', function (data) {
            // console.log(data)
            deferred.resolve(JSON.parse(data));
        })
        .on('error', function (err) {
            console.log(err);
            return deferred.resolve(err);
        })
        .exec();
    return  deferred.promise;
}
 
exports.performSearch = performSearch;

NodeJS является однопоточным, который реализован с помощью обработчика событий. Поэтому «тяжелая» логика должна выполняться асинхронно. Я использую Q в моем коде.
Q — это библиотека для создания и составления асинхронных обещаний в JavaScript.

Таким образом, я могу «освободить» зацикливатель событий и создать асинхронные запросы к моему механизму ES и получать чистые обратные вызовы через уровни кода, используя Q.

Через некоторое время я обнаружил необходимость иметь обширный API. Я использовал ExpressJS для этой цели.

ExpressJS

Я хотел, чтобы инфраструктура MVC обеспечивала уровень, подобный rest-api, который будет обрабатывать все запросы API на моей стороне сервера (NodjeJS).

Я пошел в ExpressJS, который, по-видимому, является самой популярной веб-инфраструктурой для Node.js среди веб-разработчиков (мы, как опытные разработчики открытого кода, знаем, что сообщество имеет значение!).

Я одержим структурой проекта. Я из мира Java, и иногда проекты javascript кажутся мне джунглями. Я искал популярный и традиционный способ структурировать свой проект NodeJS вместе с ExpressJS.

Поэтому, поиграв с фреймворком, я обнаружил, что с Yeoman и generator-express вы быстро генерируете структуру проекта Nodejs, включая все необходимые библиотеки expressJS, чтобы вы могли работать.

Дерево моего проекта выглядело так:

nodejstree

Пример контроллера ExpressJS:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
var express = require('express');
var router = express.Router();
var esService = require('../services/esService');
var Q = require('q');
 
 
 
router.get("/search", function (req, res) {
    var termToSearch = req.query.termToSearch;
    console.log("termToSearch=" + termToSearch);
    Q(esService.performSearch(termToSearch)
    ).then(function (data) {
            res.send("Session: %j", data);
        });
})

Контроллер вызывает метод perfomSearch с использованием esService и асинхронно возвращает результаты обратно клиенту JS, используя обещания.

Это код клиента JS, который отображает результаты в элемент HTML:

* Я использовал библиотеку prettyPrint, чтобы красиво распечатать результат json на экране:

1
2
3
4
5
6
7
8
9
function handleClick() {
    var inputParam = document.querySelector("#myinput").value;
    $.get('http://localhost:3000/search?termToSearch=' + inputParam, function (responseText) {
        console.log(responseText);
        $("#resultlist").append(prettyPrint(responseText));
    });
 
    return false;
}

эс

Идан.

Ссылка: Мой опыт использования ElasticSearch NodeJS и ExpressJS от нашего партнера по JCG Идана Фридмана в блоге IdanFridman.com .