CLOVER🍀

That was when it all began.

ElasticsearchのJavaScriptクライアントを試す

ElasticsearchはふだんJavacurlで使っているのですが、ちょっとJavaScript
クライアントも試してみたいなと思いまして。

elasticsearch.js

Java以外のプログラミング言語でのクライアントプログラミングをちょっと
覚えておこうというのが趣旨です。

今回は、ドキュメントの登録と検索あたりを軽く触ってみます。

ドキュメントは、こちらを参照。

Quick Start

Configuration

API

About

インストール

インストール方法は、こちらに記載があります。

About

まあ、こんな感じで。

$ npm i --save elasticsearch

あと、動作確認はテストコードで行おうと思いますので、MochaとChaiを入れておきます。

$ npm i --save-dev mocha chai

テストコードは、「test」ディレクトリに入れておくものとします。

$ mkdir test

package.jsonのscriptsには、こんな感じで書いておきました。

  "scripts": {
    "test": "mocha"
  },

ドキュメントの登録

それでは、まずはドキュメントの登録から行ってみます。

こちらを参考に。

Quick Start

API create

できあがったコードは、こんな感じ。今回は書籍をお題に、3つドキュメントを登録します。
test/insert-doc-test.js

const chai = require("chai");
chai.should();

const elasticsearch = require("elasticsearch");

describe("Elasticsearch JavaScript Client test", () => {
    it("register documents", () => {
        const client = new elasticsearch.Client({
            host: "localhost:9200"
        });

        return client.create({
            index: "myindex",
            type: "mytype",
            id: "978-4048662024",
            refresh: "true",
            body: {
                isbn: "978-4048662024",
                title: "高速スケーラブル検索エンジン ElasticSearch Server",
                price: 2800
            }
        })
        .then(() =>
              client.create({
                  index: "myindex",
                  type: "mytype",
                  id: "978-4774161631",
                  refresh: "true",
                  body: {
                      isbn: "978-4774161631",
                      title: "[改訂新版] Apache Solr入門 ~オープンソース全文検索エンジン",
                      price: 3888
                  }
              })
         )
        .then(() =>
              client.create({
                  index: "myindex",
                  type: "mytype",
                  id: "978-4774127804",
                  refresh: "true",
                  body: {
                      isbn: "978-4774127804",
                      title: "Apache Lucene 入門 〜Java・オープンソース・全文検索システムの構築",
                      price: 3200
                  }
              })
         );
    });
});

最初なので、軽く説明。

まずはrequireします。

const elasticsearch = require("elasticsearch");

続いて、ElasticsearchのClientを作成。

        const client = new elasticsearch.Client({
            host: "localhost:9200"
        });

今回は接続先のみ指定していますが、その他の指定可能な設定はこちらを参照しましょう。
Configuration

Client#createでドキュメントの登録ができますが、

        return client.create({
            index: "myindex",
            type: "mytype",
            id: "978-4048662024",
            refresh: "true",
            body: {
                isbn: "978-4048662024",
                title: "高速スケーラブル検索エンジン ElasticSearch Server",
                price: 2800
            }
        })

API全般的にPromiseが返ってくるようなので、thenでつなげて後続の実装ができます、と。

        .then(() =>
              client.create({
                  index: "myindex",
                  type: "mytype",
                  id: "978-4774161631",
                  refresh: "true",
                  body: {
                      isbn: "978-4774161631",
                      title: "[改訂新版] Apache Solr入門 ~オープンソース全文検索エンジン",
                      price: 3888
                  }
              })
         )

なお、「refresh: "true"」を入れているのは、即座に検索できるようにするためです。用意したテストケースの
都合上、すぐに検索が走るのですがデフォルトは「refresh: "false"」なのでその時点ではまだ登録した
ドキュメントが見えなかったりします。

通常は、「refresh: "false"」を選択するのでしょう。

検索

続いて、登録したドキュメントを検索してみます。

結果のコードは、このように。

とりあえず全件取得するクエリと、価格が3,500円を越えるものに絞って検索の2パターン書いています。
test/search-doc-test.js

const chai = require("chai");
chai.should();

const elasticsearch = require("elasticsearch");

describe("Elasticsearch JavaScript Client test", () => {
    it("search documents", () => {
        const client = new elasticsearch.Client({
            host: "localhost:9200"
        });

        return client.search({
            index: "myindex",
            type: "mytype",
            q: "*",
            sort: [ "price:asc" ]
        })
        .then(res => {
            const hits = res.hits.hits;

            res.hits.total.should.equal(3);

            const esBook = hits[0]["_source"];
            esBook["isbn"].should.equal("978-4048662024");
            esBook["title"].should.equal("高速スケーラブル検索エンジン ElasticSearch Server");
            esBook["price"].should.equal(2800);

            const luceneBook = hits[1]["_source"];
            luceneBook["isbn"].should.equal("978-4774127804");
            luceneBook["title"].should.equal("Apache Lucene 入門 〜Java・オープンソース・全文検索システムの構築");
            luceneBook["price"].should.equal(3200);

            const solrBook = hits[2]["_source"];
            solrBook["isbn"].should.equal("978-4774161631");
            solrBook["title"].should.equal("[改訂新版] Apache Solr入門 ~オープンソース全文検索エンジン");
            solrBook["price"].should.equal(3888);
        })
        .then(() => client.search({
            index: "myindex",
            type: "mytype",
            q: "price: [3500 TO *]",
            sort: [ "price:asc" ]
        }))
        .then(res => {
            res.hits.total.should.equal(1);

            const hits = res["hits"]["hits"];

            const solrBook = hits[0]["_source"];
            solrBook["isbn"].should.equal("978-4774161631");
            solrBook["title"].should.equal("[改訂新版] Apache Solr入門 ~オープンソース全文検索エンジン");
            solrBook["price"].should.equal(3888);
        });
    });
});

ElasticsearchのClientを生成しているところは先ほどと同じですが、検索にはClient#searchを使用します。

        return client.search({
            index: "myindex",
            type: "mytype",
            q: "*",
            sort: [ "price:asc" ]
        })

Quick SearchにはQuery DSLを使う例もあるのですが、今回はシンプルに「q」パラメーターで指定することに
しました。

searchの結果もやはりPromiseとなるので、結果はthenで読むようにしています。

        .then(res => {
            const hits = res.hits.hits;

            res.hits.total.should.equal(3);

            const esBook = hits[0]["_source"];
            esBook["isbn"].should.equal("978-4048662024");
            esBook["title"].should.equal("高速スケーラブル検索エンジン ElasticSearch Server");
            esBook["price"].should.equal(2800);

            const luceneBook = hits[1]["_source"];
            luceneBook["isbn"].should.equal("978-4774127804");
            luceneBook["title"].should.equal("Apache Lucene 入門 〜Java・オープンソース・全文検索システムの構築");
            luceneBook["price"].should.equal(3200);

            const solrBook = hits[2]["_source"];
            solrBook["isbn"].should.equal("978-4774161631");
            solrBook["title"].should.equal("[改訂新版] Apache Solr入門 ~オープンソース全文検索エンジン");
            solrBook["price"].should.equal(3888);
        })

Elasticsearchのレスポンスがそのまま渡ってくるようなイメージなので、レスポンスの
オブジェクトの構造が気になる方はthenのパラメーターとして渡ってくるオブジェクトを
console.logとかしてみるとよいでしょう。

これで、最低限の単純なことはできるようになりました。