🔍

検索システムに OpenSearch を導入するまで #1

2023/10/07に公開

概要

個人で開発しているサービスにて検索機能を導入するときに AWS OpenSearch Service とローカルでの開発環境の構築で詰まる所が多かったので備忘録的記事です。

ゴール

  • ローカルに OpenSearch の開発環境を作成する
  • AWS OpenSearch Service を作成し、データの登録を行う

触れないこと

  • OpenSearch の細かなチューニング
  • OpenSearch からの検索 ( 後日、気が向いたら書く )

環境

Docker

Version: 20.10.17

OpenSearch

Version: 1.3.0

AWS OpenSearch Service

Version: 1.3.0

ローカル開発環境の構築

お馴染みの Docker で開発環境の構築を行います。
後述のマッピングで利用するための tokenizer, analyzer を利用するため、公式の Docker イメージをそのまま利用するのではなく自前で Dockerfile を用意します。

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

上記の Dockerfile を利用し docker-compose.yaml を用意します。

version: “3.9”
services:
 opensearch:
 build:
 context: opensearch
 environment:
 — discovery.type=single-node
 ports:
 — “9200:9200”
 volumes:
 — ./opensearch/data:/usr/share/opensearch/data

AWS OpenSearch Service の構築

今回は最低限の環境を構築するため t3.small.search を利用します。
AWS OpenSearch Service の場合、ローカルで追加でインストールした Plugin は既に組み込まれているため特に意識する必要はありません。

インデックスマッピングの登録

今回は簡単に、 titlecreated_at のみを登録する例を記載しています。 title には Analyzer として ja_text_analyzer を利用しています。
created_at はGo の time.Time をそのまま利用出来る date_time を指定しています。

{
 "settings": {
  "index": {
   "analysis": {
    "tokenizer": {
     "ja_text_tokenizer": {
      "type": "kuromoji_tokenizer",
      "mode": "search"
     }
    },
    "analyzer": {
     "ja_text_analyzer": {
      "tokenizer": "ja_text_tokenizer",
      "type": "custom",
      "char_filter": [
       "icu_normalizer"
      ],
      "filter": [
       "kuromoji_part_of_speech"
      ]
     }
    }
   }
  }
 },
 "mappings": {
  "properties": {
            "title": {
                "type": "text",
                "analyzer": "ja_text_analyzer"
            },
            "created_at": {
                "type": "date",
                "format": "date_time"
            }
        }
 }
}

上記 json を OpenSearch のインデックスとして登録します。
Go などのアプリケーションから行うことも出来ますが、今回は curl を用いた登録方法を利用します。
ローカルからの接続時に TLS 証明書の設定を行っていない場合は --insecure オプションをつけて操作します。
AWS OpenSearch Service の場合、 -u 以降の認証情報を必要に応じて変更してください。

curl --insecure -H “Content-Type: application/json” -XPUT <OpenSearch Address>/<Index Name> -u admin:admin -d @schemas/items.json

登録後は以下のコマンドでインデックス情報を確認することが出来ます。

curl -XGET <OpenSearch Address>/<Index Name> -u ‘admin:admin’

Go での利用方法

OpenSearch を Go から利用するため今回は opensearch-project/opensearch-go を利用します。
https://github.com/opensearch-project/opensearch-go

クライアントの初期化

OpensearchAddr には OpenSearch のドメイン名を指定します。ローカルの場合 https://localhost:9200 、 AWS OpenSearch Service の場合はインスタンス作成時に発行された ドメインエンドポイント を指定します。 OpensearchUser, OpensearchPassword はローカルの場合は共に admin 、 AWS OpenSearch Service の場合はインスタンス作成時に指定したユーザ、パスワードを指定します。
ローカルの場合は証明書を利用していないため Transport で InsecureSkipVerify: true を設定します。

opensearchConfig := opensearch.Config{
  Addresses: []string{
   OpensearchAddr,
  },
  Transport: &http.Transport{
   TLSClientConfig: &tls.Config{
    InsecureSkipVerify: true,
   },
  },
  Username: OpensearchUser,
  Password: OpensearchPassword,
}

opensearchClient, err := opensearch.NewClient(opensearchConfig)
if err != nil {
 logger.Error(err.Error())
}

データの登録

osItem := model.ItemOpensearch{
 Title:     item.Title,
 CreatedAt: item.CreatedAt,
}
b, err := json.Marshal(osItem)
if err != nil {
 return err
}
r := bytes.NewReader(b)
_, err = opensearchClient.Create("item", item.ID.String(), r) // 第一引数には OpenSearch のインデックス名を指定します。第二引数はドキュメントの ID を指定します。
if err != nil {
    return err
}

参考リンク

Discussion