Bering Note – formerly 流沙河鎮

情報技術系のこと書きます。

OpenSearchCon North America 2024「OpenSearch, Python, Serverlessの探索 - Laysa Uchoa&Yuliia Barabash, Nordcloud」

OpenSearchCon North America 2024のセッション「Exploring OpenSearch, Python, and Serverless」を日本語でまとめます。 可能な限り正確に内容を拾えるようにリスニングに努めたつもりですが、もし誤りがあればご指摘ください。

OpenSearchCon とは?

イベントページ

opensearch.org

各セッションはYouTubeで視聴可能

www.youtube.com

Exploring OpenSearch, Python, and Serverless

セッションリンクは以下.

www.youtube.com

スピーカー

  • Laysa Uchoa
    • Nordcloudのエンジニア
  • Yuliia Barabash
    • Nordcloudのエンジニア

セッションまとめ

スピーカーについて

発表者のリザとジュリア・バラバシュはドイツのミュンヘンを拠点とし、クラウドソリューションの提供に従事している。Python、Terraform、そしてAWSを中心とした技術を扱っている。
今回のセッションでは、データベース全般について触れた後、検索エンジンが解決する問題の種類について説明し、OpenSearchについて詳しく解説する。最後にOpenSearchを使用したオートコンプリート機能の実装をデモを交えて紹介する。

データベースについて

データベースはデータの保存、管理、取得に使用される。現在、300以上のデータベースが存在し、毎日新しい企業が新しいデータベースを作成している。これほど多くのデータベースが存在する理由は、構造化データや非構造化データなど、異なる種類のデータが存在し、データを取得する方法も様々で、ビジネスケースも多岐にわたるためである。グラフィカルデータベース、キーバリューデータベース、NoSQLデータベースなど、様々な種類のデータベースが利用されている。

データベース選定の具体的なシナリオ

例えばアプリケーション用のデータベースが必要になったとして、DynamoDBを選択したとする。
DynamoDBはキーバリューデータベースで、キーによって高速にデータを取得でき、JSON形式のサポートもある。Lambda関数を使用してAPI経由でデータの取得や保存を行うことができ、開始時点では問題なく動作するかもしれない。

しかし、検索を試みた際に問題が発生する。クライアントが全フィールドと全ドキュメントを横断した検索を求めたが、キーバリューデータベースは検索の専門性に欠けており、うまく動作しない。

この問題を解決するために、すべてのコードを削除するのではなく、既存のシステムを拡張できる。DynamoDBを信頼できるソースとして継続使用し、OpenSearchと統合する。データをDynamoDBに送信するたびにOpenSearchにも送信し、検索の専門性が必要な場合はDynamoDBではなくOpenSearchに問い合わせるようにする。これによりクライアントに良いユーザー体験を提供できるようになる。

検索エンジンが解決する問題の例

OpenSearchなどの検索エンジンが解決する問題について紹介する。

世界は多言語環境であり、サンフランシスコのような二カ国語都市では二つの言語を見ることができる。世界中で英語だけが話されているわけではないため、異なる言語では異なる方法でデータを保存し、取得する必要がある。ドイツ語では複合語という概念があり、二つの単語を組み合わせて一つの単語にする。例えば、オレンジジュースは「オレンジ」と「ジュース」が別々ではなく、ドイツ語では一つの単語として組み合わされる。これは検索時に明らかに影響を与える。単語が個別にトークン化されている場合とは異なる検索方法になる。OpenSearchは複数の言語をサポートしており、多言語対応は非常に良い機能である。

人間はロボットではないため、タイプ時にミスを犯すことがある。しかし、メッセージにタイプミスがあってもその内容を理解することができる。これは頭の中にファジー検索アルゴリズムがあり、意味のあるものとマッチングしようとするためである。OpenSearchも同様に賢く、この機能を持っている。少し間違いがあっても自分を信じることができるのは良いことである。
オートコンプリート機能も興味深い機能である。検索エンジンで何かを入力し始めると、検索エンジンがユーザーの心を読んで関連性の高い結果を表示する。多くの検索エンジン、もちろんOpenSearchもオートコンプリートをサポートしており、何かを入力し始めると関連性の高い結果を表示しようとする。
OpenSearchの良い機能の一つは動的マッピングである。例えばログをOpenSearchに送信する際、事前にマッピングを定義したくない場合がある。多くのSQLデータベースとは異なり、使用を開始する前にマッピングを定義する必要がないのは良いことである。
OpenSearchには他にも興味深い機能がある。特にAWS環境での多くの統合があるが、他のツールやプラグインとの統合も多数ある。OpenSearchには多くの機能があり、特に機械学習分野で新しいサポートが日々追加されている。

転置インデックス


OpenSearch転置インデックスを使用している。インデックスとは、ドキュメントを調べて単語を見つけるようなものと想像できるが、OpenSearchが行う方法は実際には単語を見つけて、その単語が見つかるドキュメントを持ち、それに対するスコアも持つという方法である。これも非常に良い仕組みである。

オートコンプリートの実装

現在、オートコンプリートを実装する4つの異なる方法が存在する。プレフィックスマッチング、N-gramマッチング、サーチアズユータイプ、コンプリーションサジェスターである。N-gramマッチングとサーチアズユータイプは性質が非常に似ており、サーチアズユータイプの方がパフォーマンスが良いため、今日はプレフィックスマッチング・サーチアズユータイプとコンプリーションサジェスターに焦点を当てる。

プレフィックスマッチング


最も簡単な方法から始める。POCを行いたい場合や、ソリューションに多くの投資をしたくない場合、人々がこのソリューションを使用するかどうか確認したい場合、プレフィックスマッチングは完璧なソリューションである。インデックスを変更する必要がなく、データを分析する必要もなく、適切なクエリを構築するだけで済む。
Python開発者として、PythonクライアントであるOpenSearch Pythonを使用する。これはAPI呼び出しのラッパーを提供し、例外管理、クラスターやインデックス、データの管理に役立つ高レベルライブラリである。

OpenSearchクライアントを使用してOpenSearchへの接続を表すクライアントを作成する。これはセッションデータとセッションの認証メタデータを保持する。シンプルなsearch呼び出しから始め、使用したいインデックスを指定する必要がある。この場合は映画を検索したいので映画インデックスを使用し、特定のタイトルを持つ特定の種類の映画を検索したい。そのためタイトルを指定し、クエリの種類としてmatch_phrase_prefixを使用する。クエリが「har」というプレフィックスにマッチする必要があることと、フレーズのプレフィックスにマッチする必要があることを指定する。

このソリューションを実装するために必要なのは、適切なクエリだけである。多くの利点があるが、大量のデータがある場合はパフォーマンスが良くない。インデックスが効率的な取得のために最適化されていないためである。

コンプリーションサジェスタ


パフォーマンスを向上させる別のアプローチがコンプリーションサジェスターである。これは高速取得と低レイテンシーリクエストに適した別のタイプである。OpenSearchのメモリ内に特別なデータ構造を構築し、非常に高速な方法でデータの分析と取得を支援する。


OpenSearchにこれを行う必要があることを知らせるために、インデックスの特別なタイプを指定する必要がある。フィールドのタイプはcompletionと呼ばれる。このタイプを指定すると、OpenSearchはtitleという名前のフィールドに対して特別なデータ構造を構築する必要があることを理解する。これは通常グラフデータ構造であり、ここではツリーとして表現する。
「harry」と「hello」を挿入したいとすると、挿入時にOpenSearchはこのデータを取得してツリーを構築する。例えば「harry」の場合、Hを最初のルートとし、AとRを配置する。「hello」の場合、ルートノートHの子としてEとLを使用する。基本的にルートHからグラフとツリーを構築し、データ取得に使用される。高速取得が保証される理由は、基本的にツリーを辿って子ノードでツリーの残りを分析し、データを取得するためである。

特別なタイプのクエリも使用する必要がある。これはsuggestと呼ばれる。このsuggestは非常に強力で、複数のサジェストタイトルを持つことができる。例えば、タイトル、著者、プロットをサジェストしたい場合、一つのクエリで複数のサジェスションを組み合わせることができる。ここでは一つのサジェストタイトルのみを持っているが、このタイトルをどのように検索できるかを知らせたい。そのためプレフィックスを指定し、この場合は「harry」で、その後どのフィールドを使用したいかを指定する。この場合はtitleである。
この方法の利点は、高速な取得が可能で、プレフィックスマッチングに適していることである。さらに、重み付けされたサジェスションを持つことも可能である。

サーチアズユータイプ



サーチアズユータイプも別のタイプのオートコンプリートである。ここでもマッピングのタイプを定義する必要があり、フィールドをどのようにマッチさせたいかを定義する。
オートコンプリートに使用したいフィールドを指定するには、search_as_you_typeを使用する必要がある。この後、OpenSearchは再びこのフィールドに対して特別なデータ構造を構築する必要があることを理解するが、この場合はサブフィールドを構築し、サブフィールドも高速取得のために最適化される。
この方法の利点は低レイテンシと高いパフォーマンスで、フルテキスト検索に使用できることである。
OpenSearchがデータを保存する方法について説明する。titleが「weather is great」だとすると、挿入時にOpenSearchプロセッサは、メインフィールドtitleに対して文を個別の単語に分割し、文字列の配列として保持する。その後、指定したN-gramの数に応じて、これらのN-gramの組み合わせを作成する。「weather is」「is great」となり、取得時にこれらのN-gramとタイトルに対してマッチングを行い、より良い結果を見つける。この組み合わせは取得プロセスを高速化し、この方法を使用することでフルテキスト検索も可能になるため、非常に強力である。

このデータタイプでデータを取得する方法について説明する。searchを実行し、インデックスにmovieを指定する。
bodyにはmulti_matchを使用できる。このmulti_matchには多くの機能があり。例えば、特定のフィールドに対するブーストやファジネスに対応できるため、ユーザーがスペルミスをしたり、適切なスペルを知らない場合に役立つ。

取得を行う際に、OpenSearchがサブフィールドを作成するため、これらのサブフィールドをfieldsで指定する必要がある。OpenSearchではワイルドカードを使用できるため、すべてのフィールドを個別に記述したくない場合はワイルドカードを使用できる。また、bool queriesを使用することも可能で、プレフィックスマッチングとフルテキスト検索を組み合わせる場合などに、特定のクエリタイプに高い優先度を設定することができる。

デモ

デモでは、プレフィックスマッチング、サーチアズユータイプ、コンプリーションサジェスターの3つの異なるタイプを紹介している。

「Harry」と入力すると、例えば「Harry and Bunny」「Harry Slowman」「Harry in Banson」などの結果が表示される。しかし、夜遅くで疲れていて「Harry」のスペルを覚えていない場合、「Hary」と入力すると結果が表示されない。

より強力なコンプリーションサジェスターを実装し、「Harry」と入力すると「Harry in B」「Harry in Benson」「Harry in Scha」が表示される。「Harry」と入力すると「Harded」も表示されるが、これはコンプリーションサジェスターのファジネス機能により、スペルミスがあってもOpenSearchが理解し、結果が完全にマッチしていなくてもいくつかの結果を提供する。これがOpenSearchの力である。

まとめ


OpenSearchについて説明すると、多くのサービスとの統合がある。例えば、データを簡単に取り込むことができ、現在はソースと宛先を指定するだけでデータの処理を支援するOpenSearchパイプラインがある。スケールも非常に簡単で、パフォーマンスも非常に良い。また、異なる機能でデータの分析と集計も可能である。