Elasticsearch サーバーレスで Suggest API 外付け実装

Kunihiko Kido
Hello! Elasticsearch.
6 min readDec 22, 2015

AWS Lambda と Amazon API Gateway を使ってサーバーレスで、Elasticsearch の API を拡張する。Suggest API 編

早く Lambda から VPC 内のリソースアクセスできるようにならないかなぁ〜と思いつつ、

今回はこれ↓のAPI化のまとめです。Elasticsearch のサジェスト用のマッピング定義やアナライザーの設定はこれ↓を参考に設定してください。

システム全体の仕組みはこれ↓と同じです。

AWS Lambda: Elasticsearch Suggest Handler

Reindex に引き続き使い回せそうなので、Github に公開しました。「Elasticsearch キーワードサジェスト日本語のための設計」に記載の「複合語によるマッチング」ロジックなどを含んだファンクションになっていますので、呼び出す側は何も気にせずユーザーの入力をリクエストするだけで済むはずです。

Runtime:

Python 2.7

Lambda Hander

lambda_function.lambda_handler

Input Event:

{
"host": "http://<your_elasticsearch_server:9200>/",
"index": "userkeyword",
"doc_type": "logs",
"query": "銀座 ランチ",
"exclude_pattern": ".{1}",
"size": 10
}
  • host: バックエンドの Elasticsearch ホスト情報
  • index: (Optional) インデックス名
  • doc_type: (Optional) ドキュメントタイプ名
  • query: ユーザーキーワード
  • exclude_pattern: (Optional) 除外パターン
  • size: (Optional) 最大返却数

例えば、上記の Input Event で以下のクエリーを Elasticsearch へリクエストします。

# Query Sample
{
"size": 0,
"query": {
"bool": {
"should": [{
"match": {
"keyword.autocomplete": {
"query": "銀座 ランチ"
}
}
}, {
"match": {
"keyword.readingform": {
"query": "銀座 ランチ",
"fuzziness": "AUTO",
"operator": "and"
}
}
}]
}
},
"aggs": {
"keywords": {
"terms": {
"field": "keyword",
"include": "銀座 .*",
"exclude": ".{1}",
"order": {
"_count": "desc"
},
"size": "10"
}
}
}
}

クエリーを変更したい場合は、templates/query.json を修正してください。

Execution result:

以下のフォーマットで結果が返却されます。

{
"items": [
{
"key": "銀座 ランチ",
"doc_count": 3
},
{
"key": "銀座 ランチ イタリアン",
"doc_count": 1
},
{
"key": "銀座 ランチ 和食",
"doc_count": 1
},
{
"key": "銀座 ランチ 子連れ",
"doc_count": 1
},
{
"key": "銀座 ランチ 安い",
"doc_count": 1
},
{
"key": "銀座 ランチ 寿司",
"doc_count": 1
},
{
"key": "銀座 ランチ 日曜",
"doc_count": 1
},
{
"key": "銀座 ランチ 肉",
"doc_count": 1
}
]
}

Amazon API Gateway の設定

Lambda ファンクション設置後、API Gateway の設定を以下の参考に設定してください。

Method, Resource and Query strings:

GET /suggest?q=
  • q: ユーザーから入力されたキーワードを指定

Cross-Origin Resource Sharing (CORS):

クロスドメインで、使用する場合は設定してください。

Integration Request:

設置済みのLambda ファンクションをバックエンドに指定します。

Mapping Templates:

Mapping Templates は API Gateway から バックエンドの Lambda へ情報を渡す設定です。Lambda の Input Event の仕様に従って、マッピングします。

# Content-Type: application/json
{
"query": "$util.urlDecode($input.params('q'))",
"host": "http://<your_elasticsearch_server:9200>",
"index": "userkeyword",
"doc_type": "logs",
"exclude_pattern": ".{1}",
"size": 8
}
  • query: q (Query String) の内容を動的に設定します。
  • host: Elasticsearch のホスト情報を静的に設定します。
  • index: 検索履歴インデックスの名称を静的に設定します。
  • doc_type: 検索履歴インデックスのドキュメントタイプの名称を静的に設定します。
  • exclude_pattern: 除外するキーワードのパターンを静的に設定します。
  • size: 最大サジェスト候補数を静的に設定します。

簡単ですが以上で、Suggest API を公開できるかと思います。

パフォーマンスの制御

API Gateway はキャッシュ機能もあるので、Elasticsearch への検索負荷が気になる場合はキャッシュの設定を有効にすれば良いかと思います。

--

--