OpenSearch をローカル環境で起動する、そしてRubyからクエリを実行する

表題のことをやってみました。 今年のre:InventでOpenSearch Serverlessが発表されたので、いい機会だしいっちょOpenSearch触ってみるかと思った次第。

最初はOpenSearch Serverlessを起動してみたりしたんですが、2〜3日過ぎたら請求が$120くらい増えててビビって消しました。

一時的な増加なのかもしれないが

ところがその数日後に請求額を見てみると、そのOpenSearchの利用料がきれいに消えていたのです。 何が起こったんでしょうね。

ともあれ、Serverlessだからといってタダで使えるわけではないので、とりあえずOpenSearchを雑に使ってみようということでローカル環境でOpenSearchを起動してみることにしたのでした。

docker-compose.yml

version: '3'

services:
  ruby-dev:
    image: ruby:3.1
    container_name: ruby-dev
    networks:
      - sandbox
    command: sleep infinity
    volumes:
      - .:/workspace

  opensearch-dashboards:
    image: opensearchproject/opensearch-dashboards:1.0.1
    container_name: opensearch-dashboards
    environment:
      OPENSEARCH_HOSTS: "https://opensearch:9200"
    ports:
      - 5601:5601
    links:
      - opensearch
    networks:
      - sandbox

  opensearch:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: opensearch
    environment:
      - cluster.name=docker-cluster
      - node.name=os-node
      - cluster.initial_master_nodes=os-node
      - bootstrap.memory_lock=true
      - http.host=0.0.0.0
      - transport.host=127.0.0.1
      - "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - /tmp/opensearch:/usr/share/opensearch/data
    ports:
      - 9200:9200
    networks:
      - sandbox

networks:
  sandbox:

Dockerfile

FROM opensearchproject/opensearch:1.1.0
RUN /usr/share/opensearch/bin/opensearch-plugin install analysis-kuromoji
RUN /usr/share/opensearch/bin/opensearch-plugin install analysis-icu

Dockerでの起動についてはこちらを参考にしています。 dev.classmethod.jp

OpenSearchの起動しているネットワーク内でRubyを実行したかったので、以下のようにRuby用のコンテナも一緒に起動しています。 Rubyのコードを実行するときはこれに入ってやる感じですね。

services:
  ruby-dev:
    image: ruby:3.1
    container_name: ruby-dev
    networks:
      - sandbox
    command: sleep infinity
    volumes:
      - .:/workspace

あとは、通常通りコンテナたちを起動してあげます。

docker compose build
docker compose up -d

ユーザー名・パスワードともに 'admin' で

DevToolsからコレクションとレコードを入れます。

PUT /songs
{}
POST songs/_bulk
{ "index": { "_index": "songs", "_id": "1" } }
{ "year": 1980, "artist": "KISS", "title": "Psyco Circus"}
{ "index": { "_index": "songs", "_id": "2" } }
{ "year": 1980, "artist": "KISS", "title": "Shandi"}
{ "index": { "_index": "songs", "_id": "3" } }
{ "year": 2020, "artist": "ラブリーサマーちゃん", "title": "豆台風"}
{ "index": { "_index": "songs", "_id": "4" } }
{ "year": 2007, "artist": "MGMT", "title": "Time to Pretend"}

データが入ったので ruby-dev コンテナに入って以下のようなスクリプトを実行してやります。

docker compose exec ruby-dev bash 

bundle install
ruby app.rb

OpenSearchダッシュボードで既に適当なデータを入れていたので、それを適当なキーワードで検索するコードです。

app.rb

require 'opensearch'
require 'hashie'

client = OpenSearch::Client.new(
  host: 'https://admin:admin@opensearch:9200',
  transport_options: { ssl: { verify: false } }
)

query = {
  'size': 5,
  'query': {
    'multi_match': {
      'fields': ['title', 'artist'],
      'query': ''
    }
  }
}

response = client.search(
  body: query,
  index: 'songs'
)

ret = Hashie::Mash.new(response['hits'])
pp ret.hits.map(&:_source)

なるほど良さそう!

root@5316a1bf29a6:/workspace# ruby app.rb 
[{"year"=>2020, "artist"=>"ラブリーサマーちゃん", "title"=>"豆台風"},
 {"year"=>2001, "artist"=>"GRAPEVINE", "title"=>"風待ち"}]

今回は適当なデータを突っ込んでみましたが、大量のデータを入れてDashboardでグラフ表示するのもやってみたいですね。 では今日はここまで。

紹介したコードはこちらにあります。

GitHub - jacoyutorius/opensearch-local-ruby: OpenSearch をローカル環境で起動し、Rubyからクエリを実行してみる。