TECH PLAY

サイオステクノロジー((DXSL))

サイオステクノロジー((DXSL)) の技術ブログ

48

1. 前書き こんにちは。 サイオステクノロジーの田川です。 今回は、キーワード検索とベクトル検索を組み合わせたハイブリッド検索を行ってみます。 対象者 Elastic Cloud のアカウントを持っている人(トライアルライセンスを含む) Elasticsearch の初心者~中級者 できるようになること Elasticsearch で日本語のハイブリッド検索(キーワード検索とベクトル検索のRRF検索)を行えるようになる。 Elasticsearch で検索用テンプレートを使った検索を行えるようになる。 前提条件 Elastic Cloud (version: 8.15.0) Elastic Cloud 上に日本語でのベクトルデータを投入済みである。 前々回の記事 に日本語でのベクトルデータの投入作業を記載しています。 (2024年11月 5日時点の情報を元に記載しています。) 2. ハイブリッド検索 以前の記事で、 日本語でのキーワード検索 、 ベクトル検索 を行いましたが、 キーワード検索では上位にランキングされるのにベクトル検索では下位にランキングされるクエリ あるいは逆に ベクトル検索では上位にランキングされるのにキーワード検索では下位にランキングされるクエリ があったりします。 これらを平準化するための一つの方法がハイブリッド検索です。 キーワード検索とベクトル検索の両方を行い、検索漏れを少なくしようというものです。 Elasticsearch では、ハイブリッド検索の方法として2種類の方法を利用可能です。 スコアベース <キーワード検索のスコア> と <ベクトル検索のスコア> から <総合的なスコア> を算出する。 順位ベース <キーワード検索の順位> と <ベクトル検索の順位> から <総合的な順位> を算出する。(RRF) 今回は、後者の方法(RRFを使った順位ベースのハイブリッド検索)を使います。 (*脚注1) 1 3. RRF Reciprocal Rank Fusion (RRF) は、複数の検索結果の順位から、最終的な順位を決定するアルゴリズムです。 score = 1 / (検索方法1での順位 + rank_constant) + ... + 1 / (検索方法nでの順位 + rank_constant) により score を計算して、score が高いものの順に検索結果を並び替えます。 (*脚注2) 2 RRFによるハイブリッド検索を行うリクエストの例: (キーワード検索:1回、ベクトル検索:1回) GET /momotaro_v3/_search { "_source": false, "fields": [ "chunk_no", "content" ], "size": 10, "retriever": { "rrf": { "retrievers": [ { "standard": { "query": { "match": { "content": "キーワード検索用クエリ" } } } }, { "knn": { "field": "text_embedding.predicted_value", "k": "10", "num_candidates": "100", "query_vector_builder": { "text_embedding": { "model_id": ".multilingual-e5-small_linux-x86_64", "model_text": "ベクトル検索用クエリ" } } } } ], "rank_window_size": "10", "rank_constant": "60" } } } RRF検索を行いたい場合、”retriever” の “rrf” を利用します。 “rrf” 内の “retrievers” 配列に、リランク元の順位を与える検索内容を記述します。 上記の例では、キーワード検索:1回、ベクトル検索:1回としていますが、 キーワード検索:2回、ベクトル検索:3回 や、キーワード検索:2回、ベクトル検索:0回 のようなことも可能です。 (ただし検索回数を多くすると、その分、遅くなったりリソースを消費したりします。) 上記のリクエスト内の “k”, “num_candidates”, “rank_window_size”, “rank_constant” の値は、 リランク処理に影響を与えるパラメータです。 おおまかに説明すると下表のようになります。 項目名 説明 上記での設定値 k ベクトル検索時に上位何件の検索結果を返すか? 10 num_candidates 各シャードで何件の候補を出すか? 100 rank_window_size 各検索時に、何件返すか? 10 rank_constant 前述の RRF のスコア計算時の定数(rank_constant) 60 (*脚注3) 3 実運用でRRFによるリランク処理を行いたい場合は、これらのパラメータの値を調整する必要があります。 今回は、サンプルですので、細かい調整は行わずに、上記の値を使用します。 4. 実際にハイブリッド検索してみる。 実際に、ハイブリッド検索を行ってみます。 検索例: キーワード検索用クエリ: “桃太郎の家来が桃太郎からもらったもの” ベクトル検索用クエリ: “桃太郎の家来が桃太郎からもらったもの” ※キーワード検索用のクエリ と ベクトル検索用のクエリは異なっていてもかまいませんが、 サンプルとして同じ内容を指定しています。 (参考)キーワード検索の結果: 第2位 "chunk_no": [ 82 ] "content": [ " 犬はきびだんごを一つもらって、桃太郎のあとから、ついて行きました。" ] ... 第3位 "chunk_no": [ 102 ] "content": [ " きじもきびだんごを一つもらって、桃太郎のあとからついて行きました。" ] (参考)ベクトル検索の結果: 第4位 "chunk_no": [ 82 ] "content": [ " 犬はきびだんごを一つもらって、桃太郎のあとから、ついて行きました。" ] ... 第6位 "chunk_no": [ 102 ] "content": [ " きじもきびだんごを一つもらって、桃太郎のあとからついて行きました。" ] ハイブリッド検索の結果: 第1位 "chunk_no": [ 82 ] "content": [ " 犬はきびだんごを一つもらって、桃太郎のあとから、ついて行きました。" ] ... 第3位 "chunk_no": [ 102 ] "content": [ " きじもきびだんごを一つもらって、桃太郎のあとからついて行きました。" ] 1位と3位にヒットしています。 他のクエリでも試したいところですが、毎回、前述のような長いリクエストを発行するのが 面倒だと思われた方もいらっしゃるかもしれません。 そういった問題を解消するために、Elasticsearchでは、検索用テンプレートの機能が用意されています。 検索用テンプレートを使用するメリットとして、下記などが挙げられます。 Python などの Client から検索する場合に、Python側のコードが簡潔になる。 検索用クエリを修正する場合、Python側のコードの修正は不要。 Elasticsearch側のクエリを書く人と、Python側の呼び出し用コードを書く人の作業分担がしやすい。 (*脚注4) 4 下記のリクエストにより、検索用テンプレートを作成します。 PUT _scripts/rrf_search_template { "script": { "lang": "mustache", "source": """{ "_source": false, "fields": [ "chunk_no", "content" ], "size": "{{size}}{{^size}}10{{/size}}", "retriever": { "rrf": { "retrievers": [ { "standard": { "query": { "match": { "content": "{{query_string}}" } } } }, { "knn": { "field": "text_embedding.predicted_value", "k": "{{size}}{{^size}}10{{/size}}", "num_candidates": "{{num_candidates}}{{^num_candidates}}100{{/num_candidates}}", "query_vector_builder": { "text_embedding": { "model_id": ".multilingual-e5-small_linux-x86_64", "model_text": "{{query_for_vector}}" } } } } ], "rank_window_size": "{{size}}{{^size}}10{{/size}}", "rank_constant": "{{rank_constant}}{{^rank_constant}}60{{/rank_constant}}" } } } """ } } 上記の検索テンプレート内では、下記のパラメータを指定可能としています。 パラメータ名 説明 ディフォルト値 size ハイブリッド検索結果の返却件数 10 query_string キーワード検索クエリ なし num_candidates ベクトル検索時のシャードごとの候補の件数 100 query_for_vector ベクトル検索クエリ なし rank_constant RRF検索時の rank_constant 60 (k=size, rank_window_size=size としています。) いったん上記で検索用テンプレートを作ってしまえば、 これ以降は検索用テンプレートを使って検索することができるようになります。 検索用テンプレートを使って検索リクエストを書いてみます。 キーワード検索用クエリ: “桃太郎の家来になった動物” ベクトル検索用クエリ: “桃太郎の家来になった動物” GET /momotaro_v3/_search/template { "id": "rrf_search_template", "params": { "query_string": "桃太郎の家来になった動物", "query_for_vector": "桃太郎の家来になった動物" } } (“id” に指定している “rrf_search_template” は、先ほど作成した検索用テンプレートの id です。) 随分と簡単に書けるようになりました。 これを実行した結果を見てみます。 (参考)キーワード検索の結果: 第2位 "chunk_no": [ 103 ] "content": [ " 犬と、猿と、きじと、これで三にんまで、いい家来ができたので..." ] (参考)ベクトル検索の結果: 第1位 "chunk_no": [ 103 ] "content": [ " 犬と、猿と、きじと、これで三にんまで、いい家来ができたので..." ] ハイブリッド検索の結果: 第1位 "chunk_no": [ 103 ] "content": [ " 犬と、猿と、きじと、これで三にんまで、いい家来ができたので..." ] キーワード検索では2位でしたが、ハイブリッド検索では1位になりました。 他の例も見てみます。 キーワード検索用クエリ: “おじいさんが山へ行ったのはなぜ” ベクトル検索用クエリ: “おじいさんが山へ行ったのはなぜ” GET /momotaro_v3/_search/template { "id": "rrf_search_template", "params": { "query_string": "おじいさんが山へ行ったのはなぜ", "query_for_vector": "おじいさんが山へ行ったのはなぜ" } } (参考)キーワード検索の結果: 第1位 "chunk_no": [ 1 ] "content": [ "...おじいさんは山へしば刈りに...行きました。" ] (参考)ベクトル検索の結果: 第2位 "chunk_no": [ 1 ] "content": [ "...おじいさんは山へしば刈りに...行きました。" ] ハイブリッド検索の結果 第1位 "chunk_no": [ 1 ] "content": [ "...おじいさんは山へしば刈りに...行きました。" ] ベクトル検索では2位でしたが、ハイブリッド検索では1位になりました。 良好な結果が得られています。 5. まとめ このように Elasticsearch では、独自に難しいロジックを組むことなく、 ハイブリッド検索を行うことができます。 今回はサンプルでデータ件数が少ないこともありますが、検索も高速です。 (*脚注5) 5 また、検索用テンプレートを活用することで呼び出し側のコードを簡潔にすることができました。 次回は、Python を使った Elasticsearch の操作について紹介したいと思います。 キーワード検索のスコア と ベクトル検索のスコア から総合的なスコアを算出したい場合は、 下記を参照してください。 https://www.elastic.co/guide/en/elasticsearch/reference/current/knn-search.html#_combine_approximate_knn_with_other_features 単純に  キーワード検索のスコア + ベクトル検索のスコア とするだけでなく、  キーワード検索のスコア + ベクトル検索のスコア*10 のようなスコア計算を行うことも可能です。 ↩︎ RRF の詳細については、下記を参照してください。 https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html https://www.elastic.co/guide/en/elasticsearch/reference/current/retriever.html#rrf-retriever-example-hybrid ↩︎ RRFによるハイブリッド検索時のパラメタの詳細は、下記を参照してください。 https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html#rrf-api https://www.elastic.co/guide/en/elasticsearch/reference/current/knn-search-api.html#knn-search-api-request-body ↩︎ 検索テンプレートの詳細については、下記を参照してください。 https://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html ( _render を使って、作成した検索テンプレートをテストすることもできます。) ↩︎ ハイブリッド検索にすれば、それだけで完璧というわけではありません。 格納するデータのチャンクサイズの調整を行ったり、検索対象のデータのメタ情報(タイトル、作成者、最終更新日時など)を考慮した検索を行った方がいい場合もあります。 その他、Elasticsearch v8.14 からは、 キーワード検索 + (Cohereなどを使った)セマンティックリランク といった手法も行えるようになりました。こちらは、今後、紹介する予定です。 ↩︎ The post Elasticsearchでのハイブリッド検索 first appeared on Elastic Portal .
アバター
1. 前書き こんにちは。 サイオステクノロジーの田川です。 今回は、Elasticsearch で実際に日本語でのベクトル検索を行ってみたいと思います。 対象者 Elastic Cloud のアカウントを持っている人(トライアルライセンスを含む) Elasticsearch の初心者~中級者 できるようになること Elasticsearch で日本語のベクトル検索(ANN)を行えるようになる。 前提条件 Elastic Cloud (version: 8.15.0) Elastic Cloud 上に日本語でのベクトル検索の準備が完了している。 前回の記事 に日本語用のベクトル検索の準備作業を記載しています。 (2024年10月28日時点の情報を元に記載しています。) 2. ベクトル検索の種類 前回、ベクトル検索を行うための準備を行いました。 今回は、実際にベクトル検索を行ってみたいと思いますが、 その前に Elasticsearch における密ベクトルに対する検索の種類について説明したいと思います。 Elasticsearch では密ベクトルに対し2種類の検索方法が用意されています。 厳密に、クエリに最も近いベクトルを検索する方法(Exact kNN) 厳密ではないが、クエリにある程度近いものを高速に検索する方法(Approximate kNN(ANN)) 今回は、ある程度近いものを取得できればよいので、後者の方法(ANN)を利用します。 (*脚注1) 1 3. ベクトル検索の実行 いくつか検索してみます。 3.1 ベクトル検索(その1) クエリ1: “桃太郎が鬼が島へ向かった際の乗り物は” まず、キーワード検索をしてみます。 ( 前回のブログ記事 の中で、momotaro_v3 インデックスに桃太郎の本文をベクトル値を含めて登録済です。) GET /momotaro_v3/_search { "_source": false, "fields": ["chunk_no", "content"], "query": { "match": { "content": "桃太郎が鬼が島へ向かった際の乗り物は" } } } 上記のキーワード検索を行っても、top 10 以内に「船」という情報は見つかりません。 次にANNベクトル検索を行ってみます。 Elasticsearch で ANNベクトル検索を行いたい場合、”knn” を利用します。 (*脚注2) 2 GET /momotaro_v3/_search { "_source": false, "fields": ["chunk_no", "content"], "knn": { "field": "text_embedding.predicted_value", "k": "10", "num_candidates": "100", "query_vector_builder": { "text_embedding": { "model_id": ".multilingual-e5-small_linux-x86_64", "model_text": "桃太郎が鬼が島へ向かった際の乗り物は" } } } } (*脚注3) 3 結果 ... 第3位 "chunk_no" : [ 133 ], "content": " 桃太郎は...また船に乗りました。..." 第4位 "chunk_no" : [ 113 ], "content": " 桃太郎も...船の進むにしたがって..." ... 第9位 "chunk_no": [ 105 ], "content": " 桃太郎と、...この船に乗り込みました。" いくつか「船」を示唆する情報がヒットしています。 ここで注目なのは、検索クエリである “桃太郎が鬼が島へ向かった際の乗り物は” から算出されるベクトル値を明示していないことです。 ベクトル検索では、検索クエリのベクトル値に近いベクトル値を持つドキュメントを検索するので、 検索クエリのベクトル値が必要なはずです。 にもかかわらずベクトル検索を行うことができます。 これは、 "query_vector_builder": { "text_embedding": { "model_id": "モデルid", "model_text": "検索したいクエリ" } } の部分に入力された情報を元に Elasticsearch が “検索したいクエリ” → ベクトルの生成 を内部的に行ってくれているためです。 このように、Elasticsearch では、ドキュメントの登録時だけでなく、 検索時もベクトル化の処理を実装することなく、ベクトル検索を行うことができます。 3.2 ベクトル検索(その2) 別の質問をしてみます。 クエリ2: “桃から産まれたのは” まず、キーワード検索をしてみます。 GET /momotaro_v3/_search { "_source": false, "fields": ["chunk_no", "content"], "query": { "match": { "content": "桃から産まれたのは?" } } } 第5位 "chunk_no": [ 40 ], "content": " そして桃の中から生まれた子だというので、この子に桃太郎という名をつけました。" ヒットはしましたが、5位に表示されました。 ベクトル検索をしてみます。 GET /momotaro_v3/_search { "_source": false, "fields": ["chunk_no", "content"], "knn": { "field": "text_embedding.predicted_value", "k": "10", "num_candidates": "100", "query_vector_builder": { "text_embedding": { "model_id": ".multilingual-e5-small_linux-x86_64", "model_text": "桃から産まれたのは?" } } } } 第1位 "chunk_no": [ 40 ], "content": " そして桃の中から生まれた子だというので、この子に桃太郎という名をつけました。" 1位に表示されました。 キーワード検索では、”産まれる” と “生まれる” は全く別の単語という扱いのため、上位にヒットしませんでしたが、 ベクトル検索では、”産まれる” と “生まれる” が近いベクトルを持っているため、 上位にヒットしたものと考えられます。 3.3 ベクトル検索(その3) ベクトル検索のちょっと変わった使い方としては、別の言語による検索も(ある程度)可能です。 クエリ3: “Who was born from a peach ?” キーワード検索では、全くヒットしません。 元の文章が日本語で書かれているのに英語で検索を行っているためです。 一方、ベクトル検索では、第3位に表示されました。 第3位 "chunk_no": [ 40 ], "content": " そして桃の中から生まれた子だというので、この子に桃太郎という名をつけました。" “peach” と “桃”、”born” と “生まれる” が近いものとして捉えられているためだと思われます。 4. まとめ 今回、ANNによるベクトル検索を行い、ある程度期待した結果を得ることができました。 しかも、独自にベクトル化の処理を実装する必要はありませんでした。 ただし、ベクトル検索は万能ではありません。キーワード検索の方が適している場合もあります。 次回は、キーワード検索とベクトル検索の両方を行うハイブリッド検索を行ってみたいと思います。 Elasticsearch は、超大規模なデータであっても動作することを念頭に、 時間やメモリを消費して厳密な値を求めることよりも、 近似値であっても、より速く、より省メモリーで算出する傾向にあるように感じます。 ANN だけでなく、統計情報の中央値などの算出に関しても、 (厳密な値ではないかもしれませんが)近似値をより早く算出するような動きになっています。 (厳密な値を求めようとして、莫大な時間がかかってタイムアウトになったり、 莫大なメモリーを必要として Out of memory になってエラーになることは避け, 近似値であっても、限られたリソース(時間、メモリ)内で答えを出そうとします。) どうしても最近傍探索を行いたいという方は、下記を参考にしてみてください。 cosineSimilarity 関数を利用しますが、ANN検索よりもかなり手間がかかります。 https://www.elastic.co/guide/en/elasticsearch/reference/current/knn-search.html#exact-knn https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-script-score-query.html https://www.elastic.co/jp/blog/text-similarity-search-with-vectors-in-elasticsearch ↩︎ Elasticsearch で、ANN検索を行う場合、”knn” パラメータを指定して検索を行います。 (ANNなのに”knn”を指定するのでややこしいのですが、そういう風になっている、と理解してください。) ↩︎ “.multilingual-e5-small_linux-x86_64” では、検索クエリのプレフィックスとして “query: ” を付けた方がいいという仕様のようですが、 今回は、サンプルなので、プレフィックスは付けていません。 https://huggingface.co/intfloat/multilingual-e5-small#faq ↩︎ The post Elasticsearchでのベクトル検索 first appeared on Elastic Portal .
アバター
こんにちは。 サイオステクノロジーの田川です。 今回は、ベクトル検索のための準備を行います。 対象者 Elastic Cloud のアカウントを持っている人(トライアルライセンスを含む) Elasticsearch の初心者~中級者 できるようになること Elastic Cloud でベクトル検索を行うための準備が完了する。 (今回は、まだ、ベクトル検索は行いません。) 前提条件 Elastic Cloud (version: 8.15.0) Elastic Cloud 上のインデックスにデプロイメントを作成済 (2024年10月21日時点の情報を元に記載しています。) 1. ベクトル検索とは 前回、形態素解析を適用したことで、随分と日本語の検索がしやすくなりましたが、 “桃太郎の家来になった鳥は?” のような検索を行っても望んでいるような検索結果にはなりません。 (検索しても関係が薄そうなドキュメントが多数ヒットしてしまいます。) なぜなら、人間は ”きじ”が”鳥”の一種であること を知っていますが、 単なるキーワード検索では “きじ” != “鳥” となるため、 きじを含むドキュメントがヒットしないのです。 このような問題の解決策の一つがベクトル検索になります。 例) “りんご”は、甘い果物。 “いちご”も甘い果物。 “犬”は(果物ではなく)動物 → よって、”りんご” と “いちご” は近い関係にあり、”りんご” と “犬” は、それよりも遠い関係にある。 ベクトル検索を使うと、このように意味の近いものを検索しやすくなります。 また、 “桃から産まれたのは?” をキーワード検索しても、関連が低そうなドキュメントが上位にヒットしてしまいます。 これは、”桃から産まれる” という文章の意味を Elasticsearch が理解していないため、 キーワード検索では、似たような意味のドキュメントを見つけることができないのです。 これもベクトル検索を行うことで、”桃から産まれる” に意味が近い(似ている)ドキュメントを 検索できるようになります。 (*脚注1) 1 2. ベクトルの種類 ベクトル化を行う前に、ベクトルの種類について説明しておきます。 ベクトルの種類は大きく分けて次の2つになります。 疎ベクトル ほとんどの要素が0で、少数の0でない値を持つベクトル。 データ量が少なく、高速 単純な単語の出現を示すことなど簡素な表現に向いている。 密ベクトル ほとんどの要素が0以外の値を持つベクトル。 データ量が多く、表現力が豊か。 自然言語や画像などの表現に向いている。 Elasticsearch では、疎ベクトル(sparse_vector)も、密ベクトル(dense_vector)も、 どちらも利用可能です。 詳細な説明はここでは省略しますが、小説の文章を検索したい場合は 疎ベクトルよりも密ベクトルの方が適しているため、今回は密ベクトルを利用します。 (*脚注2) 2 3. Elasticsearch でのベクトル検索の準備 Elasticsearch で日本語のベクトル検索を行いたい場合、準備作業として以下が必要となります。 3.1. 日本語の形態素解析用のプラグインのインストール 3.2. トレーニングされたモデルのインストール 3.3. パイプラインの作成 3.4. ベクトル値を格納するフィールドの作成 3.1 日本語の形態素解析用プラグインのインストール これは 前回 analysis-icu と analysis-kuromoji を追加インストール済なので、 ここでは説明は省略します。 3.2 トレーニングされたモデルのインストール Elasticsearch では、日本語用にトレーニングされたモデルとして、あらかじめ、以下の2つが用意されています。 model 次元数 .multilingual-e5-small_linux-x86_64 384 cl-tohoku__bert-base-japanese-v3 768 今回は、サンプルデータですので、軽量な .multilingual-e5-small_linux-x86_64 をインストールします。 (*脚注3) 3 手順: Elastic Cloud へログインします。 デプロイメント一覧からデプロイメント(このブログでは “SIOS-BLOG-SAMPLE-1” )の Manage をクリックします。 Edit 左のメニューから Edit をクリックします。 Edit内の各種設定を行います。 – Enable Autoscaling for: “Machine Learning only” となっていることを確認します。 なっていない場合は、”Machine Learning only” に変更します。 – Hot data and Content tier 厳密なサイジングに関する説明は、ここでは割愛しますが、 Machine Learning を利用する場合、Hot data and Content tier に割り当てる zone は、 最低でも 2 にしておいた方がいいです。 ここでは、2 zones としておきます。(あくまでもサンプル用の設定です。本番運用時には、きちんとしたサイジング設計が必要です) – Machine Learning instances Machine Learning instances の Minimum Size per zone は、4GB または、それ以上に変更します(モデルの展開に4GB程度必要になります)。 変更後、一番下の [Save]をクリックします。 反映にしばらくかかるので、待ちます。 左のメニューから Kibana をクリックします。 Kibana を Open し、Home 画面へ戻ります。 Home画面の左のメニューから Analytics の Machine Learning をクリックします。 Machine Learning の画面が表示されます。 左のメニューの中から、 Model Management の Trained Models をクリックします。 Elasticsearch であらかじめ用意されているモデルの一覧が表示されます。 この右上の [Add trained model] をクリックします。 次に、下図のようなダイアログが表示されるので、 Intel and Linux Optimized .multinlingual-e5-small_linux-x86_64 を選択してください。(※ディフォルトでは、上部にある .elser_model_2_linux-x86_64 が選択されています。) .multinlingual-e5-small_linux-x86_64 を選択後、下の [Download] をクリックします。 .multinlingual-e5-small_linux-x86_64 のダウンロードが開始されるので、しばらく待ちます。 .multinlingual-e5-small_linux-x86_64 のダウンロードが終了すると、 元のモデル一覧中の .multilingual-e5-small_linux-x86_64 のステータスが Ready to deploy に変わるので、右の3点メニューから ▷ Deploy をクリックします。 下図のようなダイアログが表示されるので、ディフォルトのまま [Start] をクリックします。 上図の設定値を転記すると、以下のようになります。 項目 設定値 Deployment ID .multilingual-e5-small_linux-x86_64 Priority normal Number of allocations 1 Threads per allocation 1 .multilingual-e5-small_linux-x86_64 モデルのデプロイが始まり、 モデル一覧中の .multilingual-e5-small_linux-x86_64 モデルのステータスが Starting deployment… に変わります。デプロイが終了するまで、しばらく待ちます。 しばらく待っても変わらない場合は、右上の [Refresh] を押してみてください。 (それでも変わらない場合は、再びしばらく待ってから[Refresh]を押してみてください。) デプロイが完了すると、 モデル一覧中の .multilingual-e5-small_linux-x86_64 モデルのステータスが Deployed に変わります。 なお、機械学習モデルがインストールされることで、Elasticsearchの1時間あたりの利用料金が若干上昇します。 3.3 パイプラインの作成 前述でインストールしたモデルを使ってベクトル化を行えるよう、パイプラインを作成します。 Elasticsearch で言うところのパイプラインというのは、ざっくり説明すると、ドキュメント投入時に行われる処理になります。 パイプラインで、何らかの処理が行われます。 (今回の記事の中では、文字列 → ベクトル化の処理) 参考URL https://www.elastic.co/guide/en/elasticsearch/reference/current/ingest.html 下記のリクエストを Elastic Cloud の Console に入力し、実行します。 パイプライン作成リクエスト: PUT /_ingest/pipeline/japanese-text-embeddings { "description" : "Text embedding pipeline", "processors" : [ { "inference": { "model_id": ".multilingual-e5-small_linux-x86_64", "target_field": "text_embedding", "field_map": { "content": "text_field" } } } ] } 上記で作成した japanese-text-embeddings パイプラインの意味は、次のとおりです。 content フィールドに格納された文字列を .multilingual-e5-small_linux-x86_64 を使ってベクトル化し、 算出されたベクトル値を text_embedding フィールドに格納します。 作成したパイプラインをテストすることも可能です。 パイプラインのテスト用のリクエストを Console から発行してみます。 GET _ingest/pipeline/japanese-text-embeddings/_simulate { "docs": [ { "_source": { "content": "むかし、むかし、あるところに" } } ] } レスポンス: { "docs": [ { "doc": { ... "_source": { "text_embedding": { "predicted_value": [ ... 384次元のベクトル値 ... ], "model_id": ".multilingual-e5-small_linux-x86_64" }, "content": "むかし、むかし、あるところに" }, ... } } ] } うまく動いていそうです。 3.4 ベクトル値を格納するフィールドの作成 前述のパイプラインを利用してベクトル化された値を格納できるよう、新たなインデックスを作成します。 用途 項目 値 インデックス インデックス名 momotaro_v3 チャンク番号用 フィールド名 chunk_no フィールドタイプ integer 本文用 フィールド名 content フィールドタイプ text 登録用アナライザー ja_kuromoji_index_analyzer 検索用アナライザー ja_kuromoji_search_analyzer ベクトル値(の親フィールド)用 フィールド名 text_embedding フィールドタイプ (マルチフィールド)(*1) (*1) text_embedding フィールドは、内部に別フィールド(model_id, predicted_value)を持つマルチフィールドとします。 マルチフィールドの詳細については、下記を参照してください。 (一般的なリレーショナルデータベースのカラムにはない考え方です) https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html#types-multi-fields https://www.elastic.co/guide/en/elasticsearch/reference/current/multi-fields.html text_embedding 内の子フィールド 用途 項目 値 ベクトルのモデルid用 フィールド名 model_id (*2) フィールドタイプ keyword 最大長 256 ベクトル値用 フィールド名 predicted_value フィールドタイプ dense_vector 次元数 384 (*2) 今回の設定では、model_id に格納される値は、”.multilingual-e5-small_linux-x86_64″固定となります。 これらを踏まえて、インデックス “momotaro_v3” を作成します。 下記のリクエストを Elastic Cloud の Console に入力し、実行します。 momotaro_v3 インデックスの作成リクエスト: PUT /momotaro_v3 { "settings": { "index": { "number_of_shards": 1, "number_of_replicas": 1, "refresh_interval": "3600s" }, "analysis": { "char_filter": { "ja_normalizer": { "type": "icu_normalizer", "name": "nfkc_cf", "mode": "compose" } }, "tokenizer": { "ja_kuromoji_tokenizer": { "mode": "search", "type": "kuromoji_tokenizer", "discard_compound_token": true, "user_dictionary_rules": [ "きびだんご,きびだんご,キビダンゴ,カスタム名詞", "鬼が島,鬼が島,オニガシマ,カスタム名詞" ] } }, "analyzer": { "ja_kuromoji_index_analyzer": { "type": "custom", "char_filter": [ "ja_normalizer", "kuromoji_iteration_mark" ], "tokenizer": "ja_kuromoji_tokenizer", "filter": [ "kuromoji_baseform", "kuromoji_part_of_speech", "cjk_width", "ja_stop", "kuromoji_number", "kuromoji_stemmer" ] }, "ja_kuromoji_search_analyzer": { "type": "custom", "char_filter": [ "ja_normalizer", "kuromoji_iteration_mark" ], "tokenizer": "ja_kuromoji_tokenizer", "filter": [ "kuromoji_baseform", "kuromoji_part_of_speech", "cjk_width", "ja_stop", "kuromoji_number", "kuromoji_stemmer" ] } } } } } momotaro_v3 インデックスのマッピング作成のリクエスト: PUT /momotaro_v3/_mappings { "dynamic": false, "properties": { "chunk_no": { "type": "integer" }, "content": { "type": "text", "analyzer": "ja_kuromoji_index_analyzer", "search_analyzer": "ja_kuromoji_search_analyzer" }, "text_embedding": { "properties": { "model_id": { "type": "keyword", "ignore_above": 256 }, "predicted_value": { "type": "dense_vector", "dims": 384 } } } } } 4. ドキュメントのコピー(Reindex) Reindex API を使って、momotaro_v2 から momotaro_v3 へドキュメントをコピーします。 その際、pipelineに “japanese-text-embeddings” を指定します。 (これにより、momotaro_v3 の “content” フィールドへ値を格納する際にベクトル化の処理が行われ、算出されたベクトル値が “text_embedding” フィールドに格納されます。) 下記のリクエストを Elastic Cloud の Console に入力し、実行します。 Reindex リクエスト: POST /_reindex?refresh=true { "source": { "index": "momotaro_v2" }, "dest": { "index": "momotaro_v3", "pipeline": "japanese-text-embeddings" } } これで、momotaro_v3 インデックスに桃太郎の本文と、本文から算出されたベクトル値が格納されます。 5. 登録されたドキュメントの確認 下記の検索リクエストを Console から発行してみます。 GET /momotaro_v3/_search レスポンス: { ... "hits": { ... "hits": [ { "_index": "momotaro_v3", ... "_source": { "chunk_no": 1, "text_embedding": { "predicted_value": [ 0.09554096311330795, ... (384次元のベクトル) ... ], "model_id": ".multilingual-e5-small_linux-x86_64" }, "content": " むかし、むかし、あるところに、..." }, ... } ] }, ... } text_embedding.predicted_value フィールドにベクトル値が格納されていることがわかります。 お気づきかもしれませんが、Elasticsearch では、ベクトル化の処理を独自に実装しなくても ベクトル化の処理が行われ、算出されたベクトル値が登録されます。 次回は、実際にベクトル検索を行ってみたいと思います。 同義語を定義することでキーワード検索でも似たような意味を持つドキュメントを検索することは可能ですが、 この記事では、同義語に関しては考慮していません。 ↩︎ Elasticsearch で疎ベクトルを扱うことは可能ですが、v8.15.0 の時点では、 ディフォルトで用意されている疎ベクトル用のモデル(ELSER)は英語の場合に推奨されるようです。日本語を利用する場合には、v8.15.0の時点では密ベクトルを利用するのがいいように思われます。 https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-elser.html ↩︎ 今回は、.multilingual-e5-small_linux-x86_64 のモデルをインストールしましたが、 eland を使って、他のモデルをインストールすることも可能です。 https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-deploy-models.html ↩︎ The post Elasticsearchでのベクトル検索の準備 first appeared on Elastic Portal .
アバター
こんにちは。 サイオステクノロジーの田川です。 前回、登録した「桃太郎」の内容を検索しようとしましたが、 うまく検索できないことがありました。 主な原因は、作成したインデックスが日本語用に設定されていなかったことにあります。 今回は、日本語に適したインデックスを作成してみます。 ※今回は、過去4回よりは、多少、難しい内容になっています。 対象者 Elastic Cloud のアカウントを持っている人(トライアルライセンスを含む) Elasticsearch の初心者~中級者 できるようになること Elastic Cloud のデプロイメントに日本語用の形態素解析に必要なプラグインを追加インストールする。 Elastic Cloud のデプロイメント内に日本語に適したインデックスを作成する。 reindex を用いて、旧インデックスから新インデックスへのドキュメントのコピーを行う。 日本語を含むキーワード検索を行う。 前提条件 Elastic Cloud (version: 8.15.0) Elastic Cloud 上にデプロイメントを作成済 (2024年10月15日時点の情報を元に記載しています。) 1. プラグインの追加インストール 日本語に適した検索を行えるようにするため、日本語の形態素解析を行えるようにします。 日本語の形態素解析の例です。 おばあさんは川へ洗濯に行きました ↓ おばあさん / は / 川 / へ / 洗濯 / に / 行きました このように形態素解析することで、日本語の検索を行いやすくなります。 日本語の形態素解析を行えるようにするため、 Elastic Cloud のデプロイメントに対し、必要なプラグインの追加インストールを行います。 Elastic Cloud へログインします。 Elastic Cloud のデプロイメント(このブログ記事では”SIOS-BLOG-SAMPLE-1″)の Manage をクリックします。 左のメニューから Edit をクリック Manage user settings and extensions をクリック Elasticsearch user settings and extensions のダイアログが表示されます。 ここで、Extensions のタブをクリックします。 追加可能なプラグインの一覧が表示されます。 ここから、 analysis-icu analysis-kuromoji の2つにチェックを入れて、ダイアログ下部の [Back] をクリックします。 (この状態では、2つのプラグインは、まだ追加されていません。) ダイアログが閉じられた後、画面下部の [Save] をクリックします。 次のような確認ダイアログが表示されるので、[Confirm] をクリックします。 [Confirm] をクリックすると、2つのプラグインの追加インストールが開始されます。 しばらく待つと、プラグインのインストールが完了し、次のような画面になります。 これで、日本語の形態素解析を行える準備ができました。 2. 日本語用のインデックスの作成準備 日本語の文章を検索するためのインデックスの作成準備を行います。 設定する項目の値を下表に記載しておきます。 項目 設定値 備考 例 インデックス名 momotaro_v2 number_of_shards 1 あくまでもサンプルなので 1 としておく。 number_of_replicas 1 あくまでもサンプルなので 1 としておく。 refresh_interval 3600s analyzer ja_kuromoji_index_analyzer 登録用アナライザー(*1) analyzer ja_kuromoji_search_analyzer 検索用アナライザー(*1) char_filter ja_normalizer (*2) char_filter kuromoji_iteration_mark 「々」、「ヽ」、「ゝ」 などの踊り字の正規化する。 “各々”→”各各” tokenizer ja_kuromoji_tokenizer (*3) user_dictionary_rules 定義する “きびだんご”と”鬼が島”を登録しておく。(*4) filter kuromoji_baseform 原形化 “来ました”→”来る” filter kuromoji_part_of_speech 不要な品詞を除去する。 “東京の天気は晴れ”→”東京”,”天気”,”晴れ” filter cjk_width 全角英数記号→半角英数記号、半角カナ→全角カナ “#A1カナ”→”#A1カナ” filter ja_stop ストップワードの除去 “この街角”→”街角” filter kuromoji_number 漢数字の半角数字化 “一二三四”→”1234” filter kuromoji_stemmer 長音の除去 “サーバー”→”サーバ” kuromoji_tokenizer などの詳細については、Elastic社の公式ドキュメントを参照してください。 https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-icu.html https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-kuromoji.html など (*1) 今回の設定内容では、登録用のアナライザーと検索用のアナライザーは同じなので、兼用することも可能ですが、将来、検索用のアナライザーにのみ同義語を登録する場合もあるため、登録用と検索用のアナライザーは別にしておくことをお薦めします。 (*2) ja_normalizer の詳細設定は下記になります。 項目 値 説明 例 type icu_normalizer Elasticsearchで提供されている char_filter . name nfkc_cf 正規分解して合成する。ただし合成文字は分解する。また、小文字への統一も行う。 “㌢”→”セ”,”ン”,”チ”, “APPLE”→”apple” mode compose 分解された文字を合成する。 “か” + “゛” → “が” (*3) ja_kuromoji_tokenizer の詳細設定は下記になります。 項目 値 説明 例 type kuromoji_tokenizer トークン化を行う。 “東京国際空港”→”東京”,”東京国際空港”,”国際”,”空港” mode search 検索を対象としたセグメンテーションで単語分割する。 “ファンクションコール”→”ファンクション”,”コール” discard_compound_token true mode=searchのときに複合語が出力されなくなる。 “東京国際空港”→”東京”,”国際”,”空港” (*4) 本来は、何をユーザー辞書に登録すべきか?を調査すべきですが、今回は、その手順を省略しています。後からユーザー辞書に単語を追加登録することは可能ですが、その場合ドキュメントの再登録が必要となります。(後からユーザー辞書に単語を追加登録しても、既にインデックスされたドキュメントに対しては影響を与えないため) ※上記以外に同義語登録もありますが、ひとまず、考慮しないでおきます。 (なお、検索用の同義語であれば後から追加しても、ドキュメントの再登録は不要です。) ※その他、N-gramを考慮して検索を行うこともありますが、今回は触れないでおきます。 3. 日本語用のインデックスの作成 前項で掲載した値を踏まえて、日本語用のインデックスを新規に作成します(インデックス名= “/momotaro_v2” )。 PUT /momotaro_v2 { "settings": { "index": { "number_of_shards": 1, "number_of_replicas": 1, "refresh_interval": "3600s" }, "analysis": { "char_filter": { "ja_normalizer": { "type": "icu_normalizer", "name": "nfkc_cf", "mode": "compose" } }, "tokenizer": { "ja_kuromoji_tokenizer": { "mode": "search", "type": "kuromoji_tokenizer", "discard_compound_token": true, "user_dictionary_rules": [ "きびだんご,きびだんご,キビダンゴ,カスタム名詞", "鬼が島,鬼が島,オニガシマ,カスタム名詞" ] } }, "analyzer": { "ja_kuromoji_index_analyzer": { "type": "custom", "char_filter": [ "ja_normalizer", "kuromoji_iteration_mark" ], "tokenizer": "ja_kuromoji_tokenizer", "filter": [ "kuromoji_baseform", "kuromoji_part_of_speech", "cjk_width", "ja_stop", "kuromoji_number", "kuromoji_stemmer" ] }, "ja_kuromoji_search_analyzer": { "type": "custom", "char_filter": [ "ja_normalizer", "kuromoji_iteration_mark" ], "tokenizer": "ja_kuromoji_tokenizer", "filter": [ "kuromoji_baseform", "kuromoji_part_of_speech", "cjk_width", "ja_stop", "kuromoji_number", "kuromoji_stemmer" ] } } } } } content フィールドの登録時に “ja_kuromoji_index_analyzer” を適用し、 content フィールドに対する検索時に “ja_kuromoji_search_analyzer” を適用するように設定します。 PUT /momotaro_v2/_mappings { "dynamic": false, "properties": { "chunk_no": { "type": "integer" }, "content": { "type": "text", "analyzer": "ja_kuromoji_index_analyzer", "search_analyzer": "ja_kuromoji_search_analyzer" } } } これで、ドキュメントを登録する準備はできました。 4. ドキュメントのコピー(Reindex) Reindex API を使って、 事前に momotaro_v1 インデックスに登録しておいた内容を、 新たに momotaro_v2 インデックスへコピーします。 momotaro_v2 インデックスへドキュメントが登録される際に、上記で設定しておいた analyzer (ja_kuromoji_index_analyzer) が適用され、適切な形態素解析が行われます。 reindex 終了時に refresh を行い、検索可能な状態にするよう refresh=true を付けておきます。 (今回のインデックスでは、リフレッシュ間隔を1時間としているため) POST /_reindex?refresh=true { "source": { "index": "momotaro_v1" }, "dest": { "index": "momotaro_v2" } } Reindex API の詳細については、下記を参照してください。 https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html なお、momotaro_v1 インデックスにデータを登録していない場合は、 momotaro_v2 インデックスへ bulk API を使って、データを登録してください。 これで momotaro_v2 インデックスにドキュメントが登録され、日本語での検索を行えるようになりました。 5. 検索してみる。 前回うまく検索できなかった”桃太郎”を検索してみます。 検索リクエスト: GET /momotaro_v2/_search { "query": { "match": { "content": "桃太郎" } } } レスポンス: { ... "hits": { "total": { "value": 31, "relation": "eq" }, "max_score": 2.3206909, "hits": [ { "_index": "momotaro_v2", "_id": "*******************", "_score": 2.3206909, "_source": { "chunk_no": 75, "content": "「桃太郎さん、桃太郎さん、どちらへおいでになります。」" } }, ... ] } } ちゃんと31件ヒットします。 (日本語用に設定されていない momotaro_v1 インデックスでは、40件でした。) “桃太郎” または “きびだんご” を含むドキュメントを検索してみます。 検索リクエスト: GET /momotaro_v2/_search { "query": { "match": { "content": "桃太郎 きびだんご" } } } レスポンス: { ... "hits": { "total": { "value": 36, "relation": "eq" }, "max_score": 4.487536, "hits": [ { "_index": "momotaro_v2", "_id": "****************", "_score": 4.487536, "_source": { "chunk_no": 62, "content": " きびだんごがうまそうにでき上がると、桃太郎のしたくもすっかりでき上がりました。" } }, ... ] } } 36件がヒットします。 (日本語用に設定されていない momotaro_v1 インデックスでは、108件でした。) “桃太郎” と “きびだんご” の両方を含むドキュメントを検索してみます。 検索リクエスト: GET /momotaro_v2/_search { "query": { "match": { "content" : { "query" : "桃太郎 きびだんご", "operator": "and" } } } } レスポンス: { ... "hits": { "total": { "value": 5, "relation": "eq" }, "max_score": 4.487536, "hits": [ { "_index": "momotaro_v2", "_id": "*******************", "_score": 4.487536, "_source": { "chunk_no": 62, "content": " きびだんごがうまそうにでき上がると、桃太郎のしたくもすっかりでき上がりました。" } }, ... ] } } 5件がヒットしました。 “桃太郎”は含むが”きびだんご”を含まないドキュメントを検索してみます。 検索リクエスト: GET /momotaro_v2/_search { "query": { "bool": { "must": [ { "match": { "content" : "桃太郎" } } ], "must_not": [ { "match": { "content": "きびだんご" } } ] } } } レスポンス: { ... "hits": { "total": { "value": 26, "relation": "eq" }, "max_score": 2.3206909, "hits": [ { "_index": "momotaro_v2", "_id": "Qv6NLJIBnwZx8PFpcU2K", "_score": 2.3206909, "_source": { "chunk_no": 75, "content": "「桃太郎さん、桃太郎さん、どちらへおいでになります。」" } }, ... ] } } 26件がヒットしました。 形態素解析の効果も確かめてみます。 検索リクエスト: GET /momotaro_v2/_search { "query": { "match": { "content" : "三にんの家来が桃太郎からもらったもの" } } } レスポンス: ... "content": " 桃太郎と、三にんの家来は、さっそく、この船に乗り込みました。" ... "content": " 犬と、猿と、きじと、これで三にんまで、いい家来ができたので、桃太郎は..." ... "content": " 犬はきびだんごを一つもらって、桃太郎のあとから、ついて行きました。" ... どのような形態素解析が行われているのか、確かめてみます。 リクエスト: GET /momotaro_v2/_analyze { "analyzer": "ja_kuromoji_search_analyzer", "text": "三にんの家来が桃太郎からもらったもの" } レスポンス: { "tokens": [ { "token": "3", "start_offset": 0, "end_offset": 1, "type": "word", "position": 3 }, { "token": "家来", "start_offset": 4, "end_offset": 6, "type": "word", "position": 7 }, { "token": "桃太郎", "start_offset": 7, "end_offset": 10, "type": "word", "position": 9 }, { "token": "もらう", "start_offset": 12, "end_offset": 15, "type": "word", "position": 11 } ] } つまり、”三にんの家来が桃太郎からもらったもの” の検索は、 “3”, “家来”, “桃太郎”, “もらう” のいずれかを含むドキュメントの検索に置き換わっています。 “三” は、”3″ に変換されています。 (検索対象のドキュメントには検索用キーワードとして”三”ではなく、”3″が登録されています。 検索用クエリ内の”三”も”3″に変換してから検索を行います。) “の”, “が”, “から” が不要な品詞と判断され除去されています。 “にん” も除去されていますが、これは、”に” と “ん” が不要な品詞と判断されているためだと思われます。 “もの” はストップワードとして除去されています(あるいは、”も” と “の” が不要な品詞と判断され削除されています)。 “もらった” が “もらう” に変換されています。。 このように、特別な形態素解析の処理を独自に実装しなくても、あらかじめ設定を行っておくことで Elasticsearch 内で自動的に形態素解析を行ってくれます。 今回は、日本語に適したインデックスを作成し、日本語でのキーワード検索ができるようになりました。 次回は、ベクトル検索について触れたいと思います。 ※参考URL https://www.elastic.co/jp/blog/how-to-implement-japanese-full-text-search-in-elasticsearch (2024-12-19) 古いインデックス名を momotaro → momotaro_v1 に訂正しました。 The post Elasticsearchでの日本語に適したインデックスの作成 first appeared on Elastic Portal .
アバター
こんにちは。 サイオステクノロジーの田川です。 今回は、インデックスに登録したドキュメントを検索してみたいと思います。 対象者 Elastic Cloud のアカウントを持っている人(トライアルライセンスを含む) Elasticsearch の初心者 できるようになること Elastic Cloud の Console から、ドキュメントに対して簡単な検索を行える。 前提条件 Elastic Cloud (version: 8.15.0) Elastic Cloud 上のインデックスにドキュメントを登録済 (2024年10月11日時点の情報を元に記載しています。) 1. 全件を検索 前回登録した「桃太郎」の内容を Elasticsearch の Search API を使って検索してみます。 Search API の詳細な仕様については、下記の公式ドキュメントを参照してください。 https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html まずは、全ての内容を検索してみます。 初回に作成した “SIOS-BLOG-SAMPLE-1” のデプロイメント内の Console を表示します。 (Console 画面の表示方法については、 Elastissearch へのインデックスの作成 のブログ記事を参照してください。) Console のリクエスト欄に下記を入力して、 ▷ をクリックします。 GET /momotaro_v1/_search 全149ドキュメントがヒットしますが、右側のレスポンス欄には10件のみが表示されます。 これは、レスポンスとして返却される件数(“size”パラメータ)のディフォルトが 10 となっているためです。 { ... "hits": { "total": { "value": 149, "relation": "eq" }, "max_score": 1, "hits": [ ... (全10件分のドキュメント) ... ] } ※注 ディフォルトでは、score の大きい順にソートされますが、 この例では、検索条件やソート条件を全て省略しているので、並び順にさほど意味はありません。 149件全部を表示したい場合は、”size” に 149以上の値を設定する必要があります。 (なお、”size” の最大値は、10000となっています。) “size” の詳細については、下記を参照してください。 https://www.elastic.co/guide/en/elasticsearch/reference/current/paginate-search-results.html 下記のリクエストを Console から発行してみます。 GET /momotaro_v1/_search { "size": 150 } すると、右側のレスポンス欄には、全149件が表示されます。 ※注 通常は、必要以上にレスポンスを取得しないことをお勧めいたします。 上記で、”size” に 150 を指定しているのは、あくまでも、”size” の働きを確認するためです。 2. 検索条件付きの検索 2.1 キーワードを1つだけ指定した検索 今度は、本文に「桃太郎」を含むドキュメントのみ検索してみます。 “match” を使って検索してみます。 “match” クエリの詳細は、下記を参照してください。 https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html 下記のリクエストを Console から発行してみます。 GET /momotaro_v1/_search { "query": { "match": { "content": "桃太郎" } } } すると、40件のドキュメントがヒットしました。 レスポンスの例: { "took": 1, ... "hits": { "total": { "value": 40, "relation": "eq" }, "max_score": 6.645262, "hits": [ ... 10件分のヒット内容 ... ] } } score が大きい順(検索条件に、よりマッチした順)での上位10件が表示されます。 “size” に 40 を指定して、”桃太郎”にマッチした全件を見てみます。 GET /momotaro_v1/_search { "query": { "match": { "content": "桃太郎" } }, "size": 40 } すると、下位の方では、”桃太郎”ではなく、”桃”にヒットしていることがわかります。 レスポンスの例: { ... "content": "...さっきの桃を重そうにかかえて来て、" ... } これは、検索用に指定した文字列の “桃太郎” が “桃”, “太”, “郎” に分解されてしまい、 “桃”, “太”, “郎” それぞれによる検索が行われているためです。 今回のサンプルでは、形態素解析を行う analyzer を指定していません。 ディフォルトの analyzer として standard analyzer が適用されますが、 standard analyzer が、そのような仕様(“桃太郎”が”桃”,”太”,”郎”に分解される)になっているためです。 standard analyzer を利用した場合に、”桃太郎”がどのように解析されるのか?を Analyze APIを使って確認してみます。 リクエスト: GET _analyze { "analyzer": "standard", "text": "桃太郎" } レスポンス: { "tokens": [ { "token": "桃", "start_offset": 0, "end_offset": 1, "type": "<IDEOGRAPHIC>", "position": 0 }, { "token": "太", "start_offset": 1, "end_offset": 2, "type": "<IDEOGRAPHIC>", "position": 1 }, { "token": "郎", "start_offset": 2, "end_offset": 3, "type": "<IDEOGRAPHIC>", "position": 2 } ] } このように “桃太郎” が、”桃”, “太”, “郎” に分解されているのがわかります。 Analyze API の詳細な説明については、下記を参照してください。 https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-analyze.html 正直なところ、何の対策もせずに standard analyzer を使って日本語を検索するのは、あまり好ましくありません。 念のため検索文字列に、”桃 太 郎” のように “桃” と “太” と “郎” の間に半角空白を入れて検索した場合にも 40件がヒットすることがわかります。 (*脚注1) 1 どうしても、”桃太郎”に合致するドキュメントのみを取得したい場合には、 下記のように、”match” ではなく “match_phrase” を指定してみてください。 “match_phrase” だと、”桃” と “太” と “郎” の並びが”桃太郎”になっているドキュメントのみがマッチします。 GET /momotaro_v1/_search { "query": { "match_phrase": { "content": "桃太郎" } }, "size": 40 } すると、ヒットする件数が31件となり、”桃太郎”を含むドキュメントのみが取得されます。 2.2 キーワードを2つ指定した検索(OR検索) 次に、「桃太郎」または「きびだんご」を含むドキュメントを検索してみます。 Elasticsearch の場合、”a” または “b” を含むドキュメントを検索したい場合は、 検索対象文字列に “a b” のように半角空白で連結して記載します。 GET /momotaro_v1/_search { "query": { "match": { "content": "桃太郎 きびだんご" } } } 108件に増えました。 これは、今回の環境では “match” による検索を行うと、 “桃”,”太”,”郎”,”き”,”び”,”だ”,”ん”,”ご” に分解されて、どれか 1文字でもマッチしたドキュメントが検索されるためです。 この検索結果の改善は、次回、行っていきたいと思います。 2.3 キーワードを2つ指定した検索(AND検索) では、「桃太郎」と「きびだんご」の両方を含むドキュメントを検索してみます。 Elasticsearch では、”a” を含み、かつ、”b” を含むドキュメントを検索したい場合、 いくつかの書き方があります。 (1) operator に “and” を指定する。 https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html#query-dsl-match-query-boolean (2) bool を指定する。 (2.1) bool と filter を指定する。 (2.2) bool と must を指定する。 (2.3) bool と should を指定する。 https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html (2.2) の bool と must を指定する方法の例です。 GET /momotaro_v1/_search { "query": { "bool": { "must": [ { "match_phrase": { "content": "桃太郎" } }, { "match_phrase": { "content": "きびだんご" } } ] } } } 5件になりました。 2.4 キーワードを2つ指定した検索(片方を含み、もう片方を含まない検索) では、「桃太郎」を含むが、「きびだんご」を含まないドキュメントを検索してみます。 “must_not”を使います。 GET /momotaro_v1/_search { "query": { "bool": { "must": [ { "match_phrase": { "content": "桃太郎" } } ], "must_not": [ { "match_phrase": { "content": "きびだんご" } } ] } } } 26件がヒットしました。 “桃太郎”を含むドキュメントが31件、 “桃太郎” と “きびだんご” の両方を含むドキュメントが5件なので、 31 – 5 = 26 と、合っています。 (*脚注2) 2 3. ソート ディフォルトでは、score が大きい順(どれだけ検索条件にマッチしているか?の順)に並び替えされますが、 業務上の要件で、指定した順序で並び替えを行いたい場合もあるかと思います (例: ドキュメントの最終更新日時が新しい順にソートしたい、など)。 そのような場合には、”sort” を指定します。 ここでは、試しに、chunk_no の昇順にソートしてみます。 GET /momotaro_v1/_search { "query": { "match_phrase": { "content": "桃太郎" } }, "sort": [ "chunk_no" ] } これで、chunk_no の昇順に結果を得ることができます。 次の10件(11件目-20件目)を取得するには、”from” に 10 を指定します。 GET /momotaro_v1/_search { "query": { "match_phrase": { "content": "桃太郎" } }, "sort": [ "chunk_no" ], "from": 10 } 上記のリクエストを発行すると、11件目から20件目が表示されます。 ※レスポンスだけを見ると、この結果が11件目から20件目であることはわかりません。 リクエスト時点で何件目から何件目までを取得しようとしているのかをきちんと把握しておく必要があります。 ※”from”を指定することで、ヒットするドキュメントが大量にある場合に、少しずつ結果を取得することが可能となります。 “sort”, “from” の詳細については、それぞれ、下記を参照してください。 https://www.elastic.co/guide/en/elasticsearch/reference/current/sort-search-results.html https://www.elastic.co/guide/en/elasticsearch/reference/current/paginate-search-results.html (*脚注3) 3 4. 取得するフィールドの指定 ディフォルトだと、全てのフィールドを取得します。 仮に、取得する必要がないフィールドがあった場合は、下記のように、 “_source”: false を指定し、かつ、”fields” に取得したいフィールド名を配列で指定します。 (下記の例では、”fields” に1つのフィールドのみ指定していますが、複数フィールドを指定可能です。) 取得するフィールドを限定することで、クエリ実行時に消費するリソースを抑えることができます。 GET /momotaro_v1/_search { "_source": false, "fields": [ "content" ], "query": { "match_phrase" : { "content" : "桃太郎" } } } レスポンスの例: { ... "hits": { ... "hits": [ { "_index": "momotaro_v1", "_id": "********************", "_score": 6.645262, "fields": { "content": [ "「桃太郎さん、桃太郎さん、どちらへおいでになります。」" ] } }, ... ] } } “fileds” の詳細は、下記を参照してください。 https://www.elastic.co/guide/en/elasticsearch/reference/current/search-fields.html 今回、紹介したクエリ以外にもいろんな種類のクエリを利用可能です。 興味がある方は、ぜひ、お試しください。 今回は、検索はできるようになりましたが、日本語の検索でうまくいかない部分がありました。 次回は、日本語用の形態素解析を行った上で、検索を行ってみたいと思います。 (2024-12-19) インデックス名を momotaro → momotaro_v1 に訂正しました。 (*脚注) anlayzerに standard ではなく、日本語用の analyzer を明示することで、 “match”:{“content”:”桃太郎”} でも”桃太郎”にマッチするドキュメントのみを取得することは可能です。 ただし、記事の内容が多くなってしまうので、今回は触れずに、次回のブログ記事で書きたいと思います。 ↩︎ must_not とはやや目的が異なりますが、score を減点する方法もあります。 – 「桃太郎」を含む場合 score を加点する。 – 「きびだんご」を含む場合 score を減点する。 scrore を減点したい場合、”negative” や “negative_boost” を指定します。 そういった細かい調整が、Elasticsearchでは可能です。 https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-boosting-query.html ↩︎ “from” を指定する以外に、”search_after”を指定する方法もあります。 https://www.elastic.co/guide/en/elasticsearch/reference/current/paginate-search-results.html#search-after ↩︎ The post Elasticsearch で検索してみよう first appeared on Elastic Portal .
アバター
こんにちは。 サイオステクノロジーの田川です。 今回はインデックスにドキュメントを登録してみたいと思います。 対象者 Elastic Cloud のアカウントを持っている人(トライアルライセンスを含む) Elasticsearch の初心者 できるようになること Elastic Cloud の Console から、インデックスにドキュメントを登録する。 前提条件 Elastic Cloud (version: 8.15.0) Elastic Cloud 上にインデックスを作成済 (2024年09月25日時点の情報を元に記載しています。) 1. 登録するドキュメントの準備 (Elasticsrearch の “ドキュメント” は、リレーショナルデータベースで言うところの “レコード” のようなものとなります。) 1.1 ドキュメントの登録方法 一般的なドキュメントの登録方法は、大きく分けると2つに分かれます。 1. 1件ずつドキュメントを登録する。 2. Bulk API を利用してドキュメントを複数件まとめて登録する。 (これら以外に、クロールしたWebページ情報を登録する方法などもあります。) ここでは、2番目の Bulk API を用いて複数件のドキュメントをまとめて登録していきます。 ※参考 Bulk API の詳細は下記を参照してください。 Bulk API | Elasticsearch Guide [8.15] | Elastic www.elastic.co なお、Bulk API を呼び出す方法として、 Elastic Cloud の Console から実行する方法 Pythonなどのプログラミングコードから呼び出す方法 がありますが、ここでは、Elastic Cloud の Console から実行する方法について記載しています。 1.2 登録するドキュメント このブログ記事内で登録するドキュメントは、「桃太郎」の本文としています。 桃太郎 (楠山 正雄) 一 むかし、むかし、あるところに、おじいさんとおばあさんがありました。まいにち、おじいさんは山へしば刈(か)りに、おばあさんは川へ洗濯(せんたく)に行きました。 ある日、おばあさんが、川のそばで、せっ… www.aozora.gr.jp 上記の青空文庫の URL から、zip ファイルをダウンロード後、ルビを除去したものを利用しています。 ルビを除去した本文を読み込んで、Bulk API用の入力データに変換しています。 (ファイルの加工方法については、Elasticsearch の話から脱線してしまうので、ここでは詳細は割愛しますが、 下記のような簡単な Python スクリプトで変換しています。) text2bulk_input.py ----------------------------------------------------- textfile: str = "./momotaro_no_ruby_utf8.txt" chunk_no: int = 0 with open(textfile, 'r', encoding="utf-8") as file: while True: one_line :str = file.readline() if one_line == '': break chunk_no += 1 # remove last crlf content = one_line.replace("\n", "") print('{"index": {}}') print(f'{{"chunk_no": {chunk_no}, "content": "{content}"}}') (*脚注1) 1 前述の Python スクリプトを実行すると、次のような Bulk API用の入力データが出力されます。 {"index": {}} {"chunk_no": 1, "content": " むかし、むかし、あるところに、おじいさんとおばあさんがありました。まいにち、おじいさんは..."} {"index": {}} {"chunk_no": 2, "content": " ある日、おばあさんが、川のそばで、せっせと洗濯をしていますと、川上から、大きな桃が一つ、"} ... {"index": {}} {"chunk_no": 148, "content": " きじはケン、ケンと鳴きながら、くるくると宙返りをしました。"} {"index": {}} {"chunk_no": 149, "content": " 空は青々と晴れ上がって、お庭には桜の花が咲き乱れていました。"} (*脚注2) 2 2. ドキュメントの登録(1ドキュメントのみ) 前述で生成された Bulk API用の入力データを Elastic Cloud の Console に貼り付けて実行してみます。 (Elastic Cloud の Console への画面遷移については、前回のブログ記事を参照してください。) Elasticsearch へのインデックスの作成 今回は Elasticsearch にインデックスを作成してみたいと思います。 対象者:Elastic Cloud のアカウントを持っている人(トライアルライセンスを含む)・Elasticsearch の初心者。 できるようになること:Elastic Cloud のデプロイメント内にインデックスを作成する。 できるようになること:Elastic Cloud のデプロイメント内にインデックスを作成する。 elastic.sios.jp 2024.09.19 ドキュメントの登録先は、前回作成した momotaro_v1 インデックスです。 いきなり全部を貼り付けることはせずに、まずは、最初の2行(1ドキュメント分)のみ貼り付けて実行してみます。 POST /momotaro_v1/_bulk?refresh=true {"index": {}} {"chunk_no": 1, "content": " むかし、むかし、あるところに、おじいさんとおばあさんがありました。まいにち、おじいさんは..."} (*脚注3) 3 ドキュメントの登録に成功したら、次のような結果がレスポンスに表示されます。 { "errors": false, "took": 26734000762, "items": [ { "index": { "_index": "momotaro_v1", "_id": "*****************", "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 0, "_primary_term": 1, "status": 201 } } ] } 上記の “_id” は、リレーショナルデータベースで言うところの主キーに該当します。 さきほどの POST メソッドにより、Elasticsearch 側で自動採番されます。 3. 登録されたドキュメントの確認 Elastic Cloud の Console から次のようなリクエストを発行してみます。 GET /momotaro_v1/_search すると、次のような結果が返ってきます。 { "took": 0, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 1, "relation": "eq" }, "max_score": 1, "hits": [ { "_index": "momotaro_v1", "_id": ""*****************", "_score": 1, "_source": { "chunk_no": 1, "content": " むかし、むかし、あるところに、おじいさんとおばあさんが...(以降省略)..." } } ] } } ※ _search の response の詳細については、下記を参照してください。 Search API | Elasticsearch Guide [8.15] | Elastic www.elastic.co 1件のドキュメントが登録され、検索できるようになっていることが確認できました。 インデックスの Overview をクリックしてみます。 (画面上は momotaro となっていますが、momotaro_v1 が正しいです。) Document count が 1 になっていることがわかります。 インデックスの Documents をクリックしてみます。 さきほど登録したドキュメントが表示されています。 4. 残りのドキュメントの登録 chunk_no : 2 ~ 149 の本文を Console から Bulk API を使って登録します。 POST /momotaro_v1/_bulk?refresh=true {"index": {}} {"chunk_no": 2, "content": " ある日、おばあさんが、川のそばで、せっせと洗濯をしていますと、川上から、大きな桃が一つ、"} {"index": {}} {"chunk_no": 3, "content": "「ドンブラコッコ、スッコッコ。"} ... {"index": {}} {"chunk_no": 148, "content": " きじはケン、ケンと鳴きながら、くるくると宙返りをしました。"} {"index": {}} {"chunk_no": 149, "content": " 空は青々と晴れ上がって、お庭には桜の花が咲き乱れていました。"} momotaro_v1 インデックスのOverviewを確認すると、 Document count = 149 となっていることがわかります。 今回は149件という比較的少ないデータ量だったので、Console への貼り付けでドキュメントの登録を行いましたが、もっと大量にある場合や、外部のファイルなどからプログラムでテキストを読み込んで登録したい場合などは、Pythonなどのプログラムからドキュメントを登録する方法が向いています。 (Pythonからの呼び出しについては、後日、説明予定です。) 次回は、登録したドキュメントを検索してみたいと思います。 (2024-12-19) インデックス名を momotaro → momotaro_v1 に訂正しました。 (*脚注) Elasticsearchの1つのドキュメントに、どのような単位で登録するか?というのは、検索精度における課題の一つとなります。 検索システムで扱う本番用データであれば、どのように分割するか?は、慎重に検討すべき問題です。 例) ・一定の文字数で区切って登録する。 ・一文ずつ登録する。 ・”。”で区切って登録する。 ・意味的な塊ごとに登録する。 また、前後のドキュメント(いわゆるチャンク)との重複をどの程度にするか?も調整が難しいポイントになります。 今回は、検索できればいい、というシンプルなサンプルデータですので、元のデータで「一文」に区切られている部分を、そのまま「1つのドキュメント」として登録しています。 ↩︎ ここでの Bulk API用の入力データでは、”_id”を指定していません。 Elasticsearch への登録時に自動的に”_id”が割り振られます。 Bulk API を利用してドキュメントを登録したり、あるいは、1件ずつドキュメントを登録する場合に、 “_id” を指定して登録することも可能と言えば可能ですが、推奨いたしません。 “_id” を指定して新規登録する場合、Elasticsearch 側で “_id” が重複していないか?といったチェックが 働くことになり、ドキュメントの登録にかかる時間が長くなります。 どうしても “_id” を指定しなければならない特別な場合を除いては、”_id” は指定しないことをお勧めします。 ↩︎ インデックスのリフレッシュ間隔を短い時間にしている場合は、refresh=true を指定しなくても検索できるようになりますが、前回のブログ記事内で refresh_interval = 3600s としているため、refresh を明示的に行う必要があります。 ↩︎ The post Elasticsearch へのドキュメントの登録 first appeared on Elastic Portal .
アバター
こんにちは。 サイオステクノロジーの田川です。 今回は Elasticsearch にインデックスを作成してみたいと思います。 対象者 Elastic Cloud のアカウントを持っている人(トライアルライセンスを含む) Elasticsearch の初心者 できるようになること Elastic Cloud のデプロイメント内にインデックスを作成する。 (インデックスは作成されますが、ドキュメントは、まだ登録しません。) 前提条件 Elastic Cloud (version: 8.15.0) Elastic Cloud 上にデプロイメントを作成済 (2024年09月17日時点の情報を元に記載しています。) 1. Elasticsearch のデータ構造 Elasticsearch のデータ構造をかなり大雑把に書くと、次のような構造となります。 クラスター → インデックス → シャード → ドキュメント → フィールド ※参考 Elasticsearch での用語とリレーショナルデータベースでの用語の対応表は、おおよそ下記のようになります。 Elasticsearch での用語 リレーショナルデータベースでの用語 デプロイメント データベース クラスター (なし) インデックス テーブル シャード (なし) ドキュメント レコード フィールド カラム ※注 Elasticsearhの仕組みとリレーショナルデータベースの仕組みは異なるため、    完全に上の表に一致するわけではありません。あくまでも、「似たようなもの」です。 前回のデプロイメントの作成 で、クラスターまでは設定出来ています。 今回は、インデックス ~ フィールド を作ります。 2. インデックスの作成準備 インデックスを作成する際、シャード数やレプリケーション数を決定しておく必要があります。 レプリケーション数は後から変更することも可能ですが、シャード数はインデックス作成時に決定したものとなります。 (シャード数を変更する方法は皆無ではありませんが、レプリカほど簡単には変更できません。) ついでに、リフレッシュ間隔も設定しておきます。 この記事ではサンプルデータとして、「桃太郎」を使用します。 今回は、更新がほとんどない少量のサンプルデータなので、下表のようにします。 項目 設定値 ディフォルト値 number_of_shards 1 1 number_of_replicas 1 1 refresh_interval 3600s 1s ※端的には、大量のドキュメントがある場合には、shard の数を増やします。  また、耐障害性や高速読み取り性能を向上させたい場合には、replica の数を増やします。 ※参考 下記の Elastic 社の公式ページによると、1シャードあたりのサイズを10~50GB程度になるようシャード数を設定した方がいいようです。詳細は、下記のページを参照してください。 Size your shards | Elasticsearch Guide [8.15] | Elastic www.elastic.co 3. Dev Tools 先ほどの設定値を踏まえ、実際に、インデックスを作成します。 そのために、Dev Tools 画面を開きます。 Elastic Cloud へログイン後、前回作成したデプロイメントの Open をクリックします。 そうすると、「Welcome home」と表示された画面へ遷移します。 「Welcome home」画面の右下にある Dev Tools をクリックします。 クリックすると、次の画面(Dev Tools 画面)が表示されます。 (Dev Tools画面への遷移方法は他にもあります。) 初回は、右側の説明画面が表示されますが、[Dismiss] をクリックすることで、 この部分を閉じることができます。 左側のリクエスト欄に GET, POST, PUT, DELETE の Web リクエストを記述することができます。 Web リクエストを記述した後 ▷ をクリックすると、そのリクエストが実行され、結果が右側のレスポンス欄に表示されます。 試しに、ライセンスを確認してみます。 左側の入力欄に GET _license と入力し、その行にカーソルを置いた状態で、 ▷ をクリックします。 右側のレスポンス欄に、次のような結果が返却されます。(uidは、伏字にしています。) { "license": { "status": "active", "uid": "***********************************", "type": "enterprise", "issue_date": "2023-03-02T00:00:00.000Z", "issue_date_in_millis": 1677715200000, "expiry_date": "2028-02-29T23:59:59.999Z", "expiry_date_in_millis": 1835481599999, "max_nodes": null, "max_resource_units": 100000, "issued_to": "Elastic Cloud", "issuer": "API", "start_date_in_millis": 1677628800000 } } なお、左側のリクエスト欄に書いたリクエストは、消さない限り、これまでに発行したリクエストが残っています。 頻繁に呼びたいリクエストは、ここに書いておけば、 ▷ をクリックするとすぐにリクエストを再発行できます。 4. インデックスの作成 Dev Tools を使って、インデックスの作成リクエストを発行します。 Dev Tools の左側にリクエスト欄に、次のように入力し、 ▷ をクリックします。 (この後、「桃太郎」の内容を登録する予定なので、作成するインデックス名は、”momotaro_v1″ とします。) PUT /momotaro_v1 { "settings": { "index": { "number_of_shards": 1, "number_of_replicas": 1, "refresh_interval": "3600s" } } } 成功すれば右側のレスポンス欄に、次のような結果が表示されます。 { "acknowledged": true, "shards_acknowledged": true, "index": "momotaro_v1" } インデックスが作成されたか、確認してみます。 Dev Tools から下記のリクエストを発行してみます。 GET /momotaro_v1/_settings 成功すると、右側のレスポンス欄に、以下のように出力されます。 { "momotaro_v1": { "settings": { "index": { "routing": { "allocation": { "include": { "_tier_preference": "data_content" } } }, "refresh_interval": "3600s", "number_of_shards": "1", "provided_name": "momotaro_v1", "creation_date": "1726546814052", "number_of_replicas": "1", "uuid": "*****************", "version": { "created": "8512000" } } } } } Elastic Cloud の画面からも確認してみます。 左上の3点メニューをクリックし、プルダウンメニューを表示します。 そこから、Search の Content を選択します。 すると、インデックス一覧画面へ遷移します。 (画面上は momotaro となっていますが、momotaro_v1 が正しいです。) 先ほど作成した momotaro_v1 が表示されています。 ただし、データはまだ登録していないので、Docs count = 0 となっています。 5. フィールドマッピングの設定 インデックスにデータを格納する前に、フィールドマッピングを設定しておきます。 今回は単純なサンプルデータなので、フィールドは下表のようにします。 フィールド名 フィールドタイプ 説明 chunk_no integer チャンク番号 content text 本文 フィールドタイプは、リレーショナルデータベースでのカラムタイプに相当します。 フィールドタイプの詳細な説明については、下記を参照してください。 Field data types | Elasticsearch Guide [8.15] | Elastic www.elastic.co 補足1 文字列型の代表的なフィールドタイプには、text と keyword がありますが、用途が異なります。 今回は、小説内の文章を全文検索したいので、text を利用します。 フィールドタイプ 説明 keyword 各種コードなど、厳密に一致する文字列を検索するのに使用する。 ソートや集計も可能。 text 文章など、あいまい検索に利用する。 補足2 ちょっとだけデータを登録して、軽く確認したい、という程度であれば、 フィールドマッピングを省略してデータを登録しても、Elasticsearch がある程度、自動で設定してくれます。また、Elastic Cloud の管理画面上のGUIを使っても、ある程度、設定可能です。 ただし、細かい設定を行いたい場合は、あらかじめフィールドマッピングを API を使って作成しておいた方がいいと思います。 補足3 Elasticsearch では、フィールドの追加は、比較的容易にできます。 しかし、フィールドの削除は、容易にはできません。 フィールドタイプの変更も、制約があります。 上記を踏まえて、フィールドマッピング用のリクエストを Dev Tools に入力します。 インデックスの一覧画面から Dev Tools の画面を開くには、画面下部の Console をクリックします。 左側のリクエスト欄に次のリクエストを入力し、 ▷ をクリックします。 PUT /momotaro_v1/_mapping { "dynamic": false, "properties": { "chunk_no": { "type": "integer" }, "content": { "type": "text" } } } 成功したら、右側のレスポンス欄に、下記が表示されます。 { "acknowledged": true } 6.フィールドマッピングの確認 実際にフィールドが作成されたか確認してみます。 まずは、Dev Tools から、下記のリクエストを送信してみます。 GET /momotaro_v1/_mapping 成功すると、右側のレスポンス欄に、以下のように出力されます。 { "momotaro_v1": { "mappings": { "dynamic": "false", "properties": { "chunk_no": { "type": "integer" }, "content": { "type": "text" } } } } } Elastic Cloud の画面からも確認してみます。 インデックス一覧画面から “momotaro_v1” をクリックします。 すると、momotaro_v1 インデックスの画面が表示されます。 この画面の “Index mappings” をクリックします。 momotaro_v1 インデックスのマッピング情報が表示されます。 chunk_no が Integer 型で、content が Text 型で作成されていることがわかります。 なお、この画面にある [+ Add field] ボタンから、新たにフィールドを追加することも可能です。 ただし、細かい設定を行いたい場合には、API を使って追加することをお薦めします。 次回は、作成したmomotaro_v1インデックスへのドキュメントを登録します。 (2024-12-19) 作成するインデックス名を momotaro → momotaro_v1 に訂正しました。 The post Elasticsearch へのインデックスの作成 first appeared on Elastic Portal .
アバター
サイオステクノロジーの田川と申します。 ここでは、Elastic に関する技術的な内容を記載していきたいと思います。 まずは、Elastic Cloud 上でのデプロイメントの作成方法について説明していきます。 Elastic Cloud 上にデータを格納したい場合、その準備としてデプロイメントを作成しておく必要があります。 対象者 Elastic Cloud のアカウントを持っている人(トライアルライセンスを含む) Elastic Cloud の初心者 本記事で、できるようになること Elastic Cloud 上にデプロイメントが作成されます。 (デプロイメントが作成されますが、ドキュメント格納用のインデックスは、本記事では作成していません。) 前提条件 Elastic Cloud version: 8.15.0 (この記事内では、Enterprise ライセンスでの画面を記載しています。  他のライセンスでは、動作しない箇所があるかもしれません。) (2024年09月10日時点の情報を元に記載しています。) デプロイメントの作成手順 1. ログイン画面 URL = https://cloud.elastic.co/login へアクセスすると、ログイン画面が表示されます。 Email 欄に ログインするユーザーの E-mail アドレスを、 Password 欄に、そのユーザーのパスワードを入力して、 [Log in] をクリックします。 2. ホーム画面 ログインに成功すると、ホーム画面へ遷移します。 URL = https://cloud.elastic.co/home ※こちらの画面では、既にいくつかのデプロイメントが作成済ですが、初期状態では空です。 3. デプロイメント作成画面 さきほどのホーム画面の上部中央にある [Create Deployment] ボタンをクリックします。 すると、デプロイメントの新規作成用画面である、 Create a deployment 画面へ進みます。 Name欄に、デプロイメント名を入力し、右下の [Create deployment] ボタンをクリックすると、デプロイメントが作成されますが、Cloud Provider や Region などを変更すると左下に表示されている料金が変化します。 さらに、Version の下にある > Advanced settings をクリックすると、いろんな設定を変更することが可能です。 これらの設定を変更すると、料金も変化します。 必要に応じて、設定を変えます。 この記事では、後で機械学習まで行う予定ですので、機械学習を行える設定にしておきます。 また、ここで扱っているデータは重要なデータではなく、あくまでもサンプルデータであり、特別、高速なレスポンスも必要としていないため、耐障害性やパフォーマンスについては最低限の値とします。 実際には、本番のサービスで必要とされている機能、耐障害性、パフォーマンス要件に合わせて、設定してください。 (これらの設定値は、デプロイメント作成後に、後述のデプロイメントの編集画面から変更することも可能です。) (この記事では、Deployment name は “SIOS-BLOG-SAMPLE-1” としておきます。 このDeployment nameは、半角英数字とハイフンのようなシンプルな名前にしておくのが賢明だと思われます。) 4. デプロイメント作成中~作成完了画面 さきほどのCreate deployment画面で設定を終了したら、右下の [Create deployment] ボタンをクリックします。 すると、次の画面が表示されます。 5分ほど待つと、次の画面になります。 (“Your deployment is ready!” が表示されます。) この画面に表示されている Username, Password は、アプリ接続時などで必要となるので忘れないようにしてください。 万が一、忘れてしまった場合は、パスワードのリセットを行ってください。 [Download] ボタンをクリックすると、CSV形式で、Username, Password がダウンロードされます。 5. デプロイメントの初期画面 さきほどの画面の右上の [Continue] ボタンをクリックすると、作成したデプロイメントの初期画面に遷移します。 URL = https://***/app/home#/getting_started (*** には、「実際にデプロイされた地域のホスト名のFQDN:ポート番号」がはいります。) 6. 作成されたデプロイメントの確認 先ほど作成したデプロイメントが正しく作成されたかどうかを確認してみます。 一度、ログアウトして、再ログインしてみます。 すると home 画面に、先ほど作成したデプロイメントが表示されていることを確認できます。 この画面の右下の Manage をクリックすると、選択したデプロイメントの管理画面へ遷移します。 7. デプロイメントの管理画面 (デプロイメント名を変更することは滅多にないと思われますが、画面中央の下部にある Deployment name の Edit から Deployment name を変更することも可能です。) デプロイメントの管理画面の左のメニューから Edit をクリックします。 8. デプロイメントの編集画面 デプロイメントの現在の設定値を知ることができます。 設定値を変更して、下にある [Save] ボタンをクリックすると変更することもできます。 [Save] ボタンは、かなり下に表示されるので、下スクロールする必要があります。 また、[Save] をクリックして設定値を変更する場合、変更内容を反映させるために時間がかかるので、注意が必要です。 参考にしたWebページ Elastic Cloud について 〜実際にデプロイメントを作ってみよう〜 - Qiita (情報は投稿時点(2022年3月頃)の話です)Elastic Cloud について 〜実際にデプロイメントを作ってみよう〜Elastic Cloud は一言でいうと、Elastic が提供する… qiita.com The post Elastic Cloud 上でのデプロイメントの作成 first appeared on Elastic Portal .
アバター