Elastic App Searchを入れた環境のElasticsearchをKibanaで覗く
概要
Elastic App Search(オンプレミス版)を入れたら、接続されているElasticsearchにどんなインデックスが作成されるのか、マッピングはどうなのYO!? Kibanaで覗いてみた結果を貼ってみます。
前回までは
前回はElastic App SearchをDockerで動かす、というのをやりました。
ここで作成した環境を使って、Kibanaで覗いてどんなインデックスが作成されてるのか、マッピングがどうなっているのか?を確認していきます。
インデックスの確認
KibanaのDevToolsでインデックス一覧を確認してみましょう。
GET _cat/indices?v&s=index
としますと、こんな結果が返りました。
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size yellow open .app-search-actastic-clusters MfM1vdoUQOmXlEyZrssgDA 1 1 1 0 5.7kb 5.7kb yellow open .app-search-actastic-clusters-name-unique-constraint bUvAnwtfTJSPANOkLhuceA 1 1 1 0 3.1kb 3.1kb yellow open .app-search-actastic-document_types 7TTmZWh-RrCEHihbO5XoaA 1 1 1 0 5.6kb 5.6kb yellow open .app-search-actastic-document_types-engine_id-slug-unique-constraint MxLayZiOQeuDLsFKAhCTDA 1 1 1 0 3.1kb 3.1kb yellow open .app-search-actastic-elasticsearch_indices taeplLguR1-Z0fFp4FV_hA 1 1 1 0 5.6kb 5.6kb yellow open .app-search-actastic-engine_document_backends 6tSqK5LWS3yZBsdHxXuJRg 1 1 1 0 5.9kb 5.9kb yellow open .app-search-actastic-engines 1AMN92uHSIuFQ-fdwsBF8w 1 1 1 0 11.3kb 11.3kb yellow open .app-search-actastic-engines-account_id-loco_moco_account_id-slug-unique-constraint sVynZmHSS2Cqb7sWs5_Lgw 1 1 1 0 3.2kb 3.2kb yellow open .app-search-actastic-engines-key-unique-constraint IKmt6hg-TRi3gPFi-b278g 1 1 1 0 3.1kb 3.1kb yellow open .app-search-actastic-index_pointers Uvi6k8njTYCARVzvq8OrsQ 1 1 1 0 6.5kb 6.5kb yellow open .app-search-actastic-loco_moco_accounts 6PrGFgdDQBSXyAyJ6UeIOA 1 1 1 0 5.5kb 5.5kb yellow open .app-search-actastic-loco_moco_accounts-key-unique-constraint k9hKYRtUT_C_XfrReFTu_A 1 1 1 0 3.1kb 3.1kb yellow open .app-search-actastic-loco_moco_api_token_engines ahOdNulqQ4iTnWI4ZVPKQQ 1 1 0 0 261b 261b yellow open .app-search-actastic-loco_moco_api_tokens VfGE9oSxSmagk7siSlQICg 1 1 2 0 13kb 13kb yellow open .app-search-actastic-loco_moco_api_tokens-authentication_token-unique-constraint 0mgrgouyR-6NxmnH1ce1fA 1 1 2 0 6.5kb 6.5kb yellow open .app-search-actastic-loco_moco_document_position_queries Ay9c593DTj6kFqEweiC89g 1 1 0 0 261b 261b yellow open .app-search-actastic-loco_moco_document_positions ACSW98cuR6aPps1KJ7ORyw 1 1 0 0 261b 261b yellow open .app-search-actastic-loco_moco_invitations 1cT1cdvpQsCgPmXT61ey8Q 1 1 0 0 261b 261b yellow open .app-search-actastic-loco_moco_roles zuheAIWIQFWCBCmXNzC0Bg 1 1 1 0 5.3kb 5.3kb yellow open .app-search-actastic-loco_moco_search_settings v5JzaCe6TUWfITL1WOF3uQ 1 1 0 0 261b 261b yellow open .app-search-actastic-reindex_jobs 0ToDVV9yStah0yjhl4et3A 1 1 0 0 261b 261b yellow open .app-search-actastic-synonyms ratUO5kaQ9S28gHG9-BKoA 1 1 0 0 261b 261b yellow open .app-search-actastic-users QDSo5ahNQGmwEYmaBiQOSg 1 1 1 0 9.7kb 9.7kb yellow open .app-search-actastic-users-email-unique-constraint Nw_eZ8LIS0yHXTD4dlN00g 1 1 1 0 3.1kb 3.1kb green open .app-search-analytics-logs-loco_togo_production-6.4.2-2019.01.04 60LlyHNLQLWyf5Vbv9tSog 1 0 4 0 55.6kb 55.6kb green open .app-search-analytics-logs-loco_togo_production-6.4.2-2019.01.06 oMgZ7QQPQKqoldBn4AhLFQ 1 0 7 0 94kb 94kb green open .app-search-app-logs-loco_togo_production-6.4.2-2019.01.04 jzumVhK7SH6hvto32KN35w 1 0 127 0 1.7mb 1.7mb green open .app-search-app-logs-loco_togo_production-6.4.2-2019.01.06 WZsyjrn8QFCXECnx0GUxnA 1 0 91 0 757kb 757kb yellow open .app-search-db-lock 7T_7cxiMRj-Kljfn3vJvaw 1 1 0 0 261b 261b yellow open .app-search-document-backend-5c2f7a47b34f5f799a8e7691 0ltdjqx2SJaxW_ufXoD6Vg 1 1 2 0 11.6kb 11.6kb green open .app-search-engine-5c2f7a47b34f5f799a8e7691 fotpWaWmQ9udK9v8VCAZ9A 1 0 2 0 24.8kb 24.8kb yellow open .app-search-esqueues-me_queue_v1_account_destroyer Tooi_zvlTMCUWBQSKLjdeA 1 1 0 0 261b 261b yellow open .app-search-esqueues-me_queue_v1_analytics_events QUVshquSRdir3ZkUDAkR8g 1 1 0 0 261b 261b yellow open .app-search-esqueues-me_queue_v1_document_destroyer O2UKg7K6SO2_c_O3AxIXTQ 1 1 0 0 261b 261b yellow open .app-search-esqueues-me_queue_v1_engine_destroyer WleKaeY8Qz-movtrVv-jfA 1 1 0 0 261b 261b yellow open .app-search-esqueues-me_queue_v1_index_adder GeTP4LIFRHOM_wgVMNoM3w 1 1 0 0 259b 259b yellow open .app-search-esqueues-me_queue_v1_indexed_doc_remover gaxVxz7kSoaPFY7JVIOcDw 1 1 0 0 261b 261b yellow open .app-search-esqueues-me_queue_v1_refresh_document_counts JvkmsO7kT2-D1JhIoLcWPg 1 1 0 0 259b 259b yellow open .app-search-esqueues-me_queue_v1_reindexer Jc2By9V5SAieI-2F1RHaMQ 1 1 0 0 261b 261b green open .kibana_1 jBWGxL9BSMKbDHXUM1D50g 1 0 3 0 11.9kb 11.9kb
ざっと眺めて
App Searchとして管理すべき情報を、ほとんどElasticsearchに入れて管理しようとしている、ということが感じられます。 よく、「Elasticsearchは全文検索のシステムであって、RDBMSじゃないんだから」などと言われることもありますが、 db_lockとかRDBMSを想起させるような名前がついたインデックスがあるのは、用途は分かりませんが面白いですね。
シャード、レプリカの設定
シャード(pri)、レプリカ(rep)の数が、ほとんどのインデックスで1/1となっています。 ログはレプリカが0になっています。
このあたりは格納されるドキュメントの数が増えると変わるのかもしれませんが、初期値としてはこのようになっているようです。
ユーザ設定
ユーザの設定については、.app-search-actastic-users
に格納されています。
POST _xpack/sql?format=csv { "query": "describe \".app-search-actastic-users\"" }
とやって、列定義を見てみましょう。
column,type,mapping cloudflare_account_id,VARCHAR,KEYWORD confirmation_auto_sign_in_token,VARCHAR,KEYWORD confirmation_auto_sign_in_token_created_at,TIMESTAMP,DATE confirmation_sent_at,TIMESTAMP,DATE confirmation_token,VARCHAR,KEYWORD confirmed_at,TIMESTAMP,DATE created_at,TIMESTAMP,DATE current_sign_in_at,TIMESTAMP,DATE current_sign_in_ip,VARCHAR,KEYWORD email,VARCHAR,KEYWORD email_status,VARCHAR,KEYWORD encrypted_password,VARCHAR,KEYWORD failed_attempts,BIGINT,LONG fv_landing,VARCHAR,KEYWORD fv_landing_ca,VARCHAR,KEYWORD fv_refdom,VARCHAR,KEYWORD fv_time,BIGINT,LONG heroku_id,VARCHAR,KEYWORD id,VARCHAR,KEYWORD last_sign_in_at,TIMESTAMP,DATE last_sign_in_ip,VARCHAR,KEYWORD locked_at,TIMESTAMP,DATE name,VARCHAR,KEYWORD picture_url,VARCHAR,KEYWORD receive_analytics_email,BOOLEAN,BOOLEAN remember_created_at,TIMESTAMP,DATE reset_password_sent_at,TIMESTAMP,DATE reset_password_token,VARCHAR,KEYWORD shopify_access_token,VARCHAR,KEYWORD shopify_shop,VARCHAR,KEYWORD sign_in_count,BIGINT,LONG unconfirmed_email,VARCHAR,KEYWORD unlock_token,VARCHAR,KEYWORD updated_at,TIMESTAMP,DATE wordpress_signup,BOOLEAN,BOOLEAN
暗号化されたパスワードを格納するカラムが用意されていることが分かります。 App Searchとしてどう使えるのかは不明ですが、wordpress_signupやheroku_idといったカラムがあるのは、そういったシステムとの連携が出来るのかな? と予感させます。
ドキュメント
前回作成したテストドキュメントは、.app-search-engine-5c2f7a47b34f5f799a8e7691
に入っていました。
match_allで中身を確認してみますと、確かに2件、テストドキュメントとして登録したものが格納されていることが確認できました。
__st_text_summary
や__st_expires_after
は、テストドキュメントを登録したときのjsonにはなかった項目ですね。
このあたりはApp Search側で付与して管理される項目のようです。
インデックス設定の確認
どんなanalyzerやtokenizerの設定がなされるのか、が気になるところです。 App SearchでEngineを追加するときに、日本語を指定したため、日本語検索用の設定が見られるのでは、と期待してこれを確認していきます。
GET .app-search-engine-5c2f7a47b34f5f799a8e7691/_settings
とやって、返ってきたjsonの中からanalysisの部分を抜き出したものが以下です。
"analysis" : { "filter" : { "front_ngram" : { "type" : "edge_ngram", "min_gram" : "1", "max_gram" : "12" }, "bigram_joiner" : { "max_shingle_size" : "2", "token_separator" : "", "output_unigrams" : "false", "type" : "shingle" }, "bigram_max_size" : { "type" : "length", "max" : "16", "min" : "0" }, "phrase_shingle" : { "max_shingle_size" : "3", "min_shingle_size" : "2", "output_unigrams" : "true", "type" : "shingle" }, "delimiter" : { "split_on_numerics" : "true", "generate_word_parts" : "true", "preserve_original" : "false", "catenate_words" : "true", "generate_number_parts" : "true", "catenate_all" : "true", "split_on_case_change" : "true", "type" : "word_delimiter_graph", "catenate_numbers" : "true", "stem_english_possessive" : "true" }, "ja-stop-words-filter" : { "type" : "stop", "stopwords" : "_english_" }, "ja-stem-filter" : { "name" : "light_english", "type" : "stemmer" } }, "analyzer" : { "i_prefix" : { "filter" : [ "cjk_width", "lowercase", "asciifolding", "front_ngram" ], "tokenizer" : "standard" }, "iq_intragram" : { "filter" : [ "cjk_width", "lowercase", "asciifolding" ], "tokenizer" : "intragram_tokenizer" }, "iq_phrase_shingle" : { "filter" : [ "cjk_width", "lowercase", "asciifolding", "phrase_shingle" ], "tokenizer" : "standard" }, "iq_text_delimiter" : { "filter" : [ "delimiter", "cjk_width", "lowercase", "asciifolding", "ja-stop-words-filter", "ja-stem-filter", "cjk_bigram" ], "tokenizer" : "whitespace" }, "q_prefix" : { "filter" : [ "cjk_width", "lowercase", "asciifolding" ], "tokenizer" : "standard" }, "iq_text_base" : { "filter" : [ "cjk_width", "lowercase", "asciifolding", "ja-stop-words-filter" ], "tokenizer" : "standard" }, "iq_text_stem" : { "filter" : [ "cjk_width", "lowercase", "asciifolding", "ja-stop-words-filter", "ja-stem-filter", "cjk_bigram" ], "tokenizer" : "standard" }, "iq_text_bigram" : { "filter" : [ "cjk_width", "lowercase", "asciifolding", "ja-stem-filter", "bigram_joiner", "bigram_max_size" ], "tokenizer" : "standard" } }, "tokenizer" : { "intragram_tokenizer" : { "token_chars" : [ "letter", "digit" ], "min_gram" : "3", "type" : "ngram", "max_gram" : "4" } } }
ja_*
という設定があるところを見ると、日本語用の設定がされていると見ることができそうです。
kuromojiやgosen、sudachiといったアプローチがなかったのは、ちょっと予想外だったところですが、cjk_bigramをうまく使ってるようです。 prefix検索用にedge_ngramを使っているところからみても、基本的にはngramでのアプローチなのかな、と見えました。
intragram_tokenizerというTokenizerの指定にも工夫がありそうですね。
マッピングの確認
複数のanalyzerが用意されていることが分かったので、フィールドとの関係を見ていきます。
bodyフィールドの定義を見てみますと、こんな感じになっていました。
"body$string" : { "type" : "text", "index_options" : "offsets", "fields" : { "delimiter" : { "type" : "text", "term_vector" : "with_positions_offsets", "index_options" : "offsets", "analyzer" : "iq_text_delimiter", "position_increment_gap" : 100 }, "enum" : { "type" : "keyword", "ignore_above" : 2048 }, "intragram" : { "type" : "text", "index_options" : "docs", "analyzer" : "iq_intragram" }, "joined" : { "type" : "text", "term_vector" : "with_positions_offsets", "index_options" : "offsets", "analyzer" : "iq_text_bigram", "position_increment_gap" : 100 }, "prefix" : { "type" : "text", "term_vector" : "with_positions_offsets", "index_options" : "docs", "analyzer" : "i_prefix", "search_analyzer" : "q_prefix" }, "stem" : { "type" : "text", "term_vector" : "with_positions_offsets", "index_options" : "offsets", "analyzer" : "iq_text_stem", "position_increment_gap" : 100 } }, "analyzer" : "iq_text_base", "position_increment_gap" : 100 }
1つのフィールドも、複数のフィールドに分けて、それぞれAnalyzerを設定していることが見て取れますね。
prefixとついたフィールドの設定を見ると、インデックス時のAnalyzerと検索時のAnalyzerが、i_prefix
とq_prefix
で違うものになっていることに気づきます。
この名前からすると、iq_*
となっていたのは、インデックス時も検索時も共通して使うもの、と理解できそうです。
終わりに
細かな設定値を1つずつ検証することはしていませんが、アプローチが感じられただけでも収穫でした。 単純な2-gramでやっているのではなく、連結したり、Prefix用にEdge-Ngramを使っていたりするところが参考になりました。
Analysisの設定やマッピングの設定は分かった、じゃあ、検索時にはどういうクエリを投げているのか?(複数フィールドを指定しているだろうし) シノニムとかは、いつ展開しているの? とか。 次は、こういうことが気になってきますね。おいおい調べてみたいところです。
ではまた。