検索のトラブルシューティング

データをクエリすると、Elasticsearchはエラー、検索結果なし、または予期しない順序で結果を返すことがあります。このガイドでは、検索のトラブルシューティング方法について説明します。

データストリーム、インデックス、またはエイリアスが存在することを確認する

Elasticsearchは、クエリしようとしているデータストリーム、インデックス、またはエイリアスが存在しない場合にindex_not_found_exceptionを返します。これは、名前を誤って入力した場合や、データが異なるデータストリームまたはインデックスにインデックスされた場合に発生する可能性があります。

exists APIを使用して、データストリーム、インデックス、またはエイリアスが存在するかどうかを確認します:

Python

  1. resp = client.indices.exists(
  2. index="my-data-stream",
  3. )
  4. print(resp)

Ruby

  1. response = client.indices.exists(
  2. index: 'my-data-stream'
  3. )
  4. puts response

Js

  1. const response = await client.indices.exists({
  2. index: "my-data-stream",
  3. });
  4. console.log(response);

コンソール

  1. HEAD my-data-stream

data stream stats APIを使用して、すべてのデータストリームをリストします:

Python

  1. resp = client.indices.data_streams_stats(
  2. human=True,
  3. )
  4. print(resp)

Ruby

  1. response = client.indices.data_streams_stats(
  2. human: true
  3. )
  4. puts response

Js

  1. const response = await client.indices.dataStreamsStats({
  2. human: "true",
  3. });
  4. console.log(response);

コンソール

  1. GET /_data_stream/_stats?human=true

get index APIを使用して、すべてのインデックスとそのエイリアスをリストします:

Python

  1. resp = client.indices.get(
  2. index="_all",
  3. filter_path="*.aliases",
  4. )
  5. print(resp)

Ruby

  1. response = client.indices.get(
  2. index: '_all',
  3. filter_path: '*.aliases'
  4. )
  5. puts response

Js

  1. const response = await client.indices.get({
  2. index: "_all",
  3. filter_path: "*.aliases",
  4. });
  5. console.log(response);

コンソール

  1. GET _all?filter_path=*.aliases

エラーの代わりに、クエリしているインデックスの一部が利用できない場合、部分的な検索結果を取得することができます。ignore_unavailabletrueに設定します:

Python

  1. resp = client.search(
  2. index="my-alias",
  3. ignore_unavailable=True,
  4. )
  5. print(resp)

Ruby

  1. response = client.search(
  2. index: 'my-alias',
  3. ignore_unavailable: true
  4. )
  5. puts response

Js

  1. const response = await client.search({
  2. index: "my-alias",
  3. ignore_unavailable: "true",
  4. });
  5. console.log(response);

コンソール

  1. GET /my-alias/_search?ignore_unavailable=true

データストリームまたはインデックスにデータが含まれていることを確認する

検索リクエストがヒットを返さない場合、データストリームまたはインデックスにデータが含まれていない可能性があります。これは、データ取り込みの問題がある場合に発生する可能性があります。たとえば、データが別の名前のデータストリームまたはインデックスにインデックスされている可能性があります。

count APIを使用して、データストリームまたはインデックス内のドキュメント数を取得します。レスポンスのcountが0でないことを確認します。

Python

  1. resp = client.count(
  2. index="my-index-000001",
  3. )
  4. print(resp)

Ruby

  1. response = client.count(
  2. index: 'my-index-000001'
  3. )
  4. puts response

Js

  1. const response = await client.count({
  2. index: "my-index-000001",
  3. });
  4. console.log(response);

コンソール

  1. GET /my-index-000001/_count

Kibanaで検索結果が得られない場合、正しいデータビューと有効な時間範囲を選択していることを確認してください。また、データビューが正しい時間フィールドで構成されていることを確認してください。

フィールドが存在し、その機能を確認する

存在しないフィールドをクエリすると、結果は返されません。field capabilities APIを使用して、フィールドが存在するかどうかを確認します:

Python

  1. resp = client.field_caps(
  2. index="my-index-000001",
  3. fields="my-field",
  4. )
  5. print(resp)

Ruby

  1. response = client.field_caps(
  2. index: 'my-index-000001',
  3. fields: 'my-field'
  4. )
  5. puts response

Js

  1. const response = await client.fieldCaps({
  2. index: "my-index-000001",
  3. fields: "my-field",
  4. });
  5. console.log(response);

コンソール

  1. GET /my-index-000001/_field_caps?fields=my-field

フィールドが存在しない場合、データ取り込みプロセスを確認してください。フィールドには異なる名前が付けられている可能性があります。

フィールドが存在する場合、リクエストはフィールドのタイプと、検索可能かつ集約可能かどうかを返します。

コンソール-レスポンス

  1. {
  2. "indices": [
  3. "my-index-000001"
  4. ],
  5. "fields": {
  6. "my-field": {
  7. "keyword": {
  8. "type": "keyword",
  9. "metadata_field": false,
  10. "searchable": true,
  11. "aggregatable": true
  12. }
  13. }
  14. }
  15. }
このインデックスのフィールドはkeyword型です。
このインデックスのフィールドは検索可能です。
このインデックスのフィールドは集約可能です。

フィールドのマッピングを確認する

フィールドの機能は、そのマッピングによって決まります。マッピングを取得するには、get mapping APIを使用します:

Python

  1. resp = client.indices.get_mapping(
  2. index="my-index-000001",
  3. )
  4. print(resp)

Ruby

  1. response = client.indices.get_mapping(
  2. index: 'my-index-000001'
  3. )
  4. puts response

Js

  1. const response = await client.indices.getMapping({
  2. index: "my-index-000001",
  3. });
  4. console.log(response);

コンソール

  1. GET /my-index-000001/_mappings

textフィールドをクエリする場合、設定されている可能性のあるアナライザーに注意してください。analyze APIを使用して、フィールドのアナライザーが値やクエリ用語をどのように処理するかを確認します:

Python

  1. resp = client.indices.analyze(
  2. index="my-index-000001",
  3. field="my-field",
  4. text="this is a test",
  5. )
  6. print(resp)

Ruby

  1. response = client.indices.analyze(
  2. index: 'my-index-000001',
  3. body: {
  4. field: 'my-field',
  5. text: 'this is a test'
  6. }
  7. )
  8. puts response

Js

  1. const response = await client.indices.analyze({
  2. index: "my-index-000001",
  3. field: "my-field",
  4. text: "this is a test",
  5. });
  6. console.log(response);

コンソール

  1. GET /my-index-000001/_analyze
  2. {
  3. "field" : "my-field",
  4. "text" : "this is a test"
  5. }

既存のフィールドのマッピングを変更するには、フィールドのマッピングを変更するを参照してください。

フィールドの値を確認する

existsクエリを使用して、フィールドに値を返すドキュメントがあるかどうかを確認します。レスポンスのcountが0でないことを確認します。

Python

  1. resp = client.count(
  2. index="my-index-000001",
  3. query={
  4. "exists": {
  5. "field": "my-field"
  6. }
  7. },
  8. )
  9. print(resp)

Ruby

  1. response = client.count(
  2. index: 'my-index-000001',
  3. body: {
  4. query: {
  5. exists: {
  6. field: 'my-field'
  7. }
  8. }
  9. }
  10. )
  11. puts response

Js

  1. const response = await client.count({
  2. index: "my-index-000001",
  3. query: {
  4. exists: {
  5. field: "my-field",
  6. },
  7. },
  8. });
  9. console.log(response);

コンソール

  1. GET /my-index-000001/_count
  2. {
  3. "query": {
  4. "exists": {
  5. "field": "my-field"
  6. }
  7. }
  8. }

フィールドが集約可能な場合、集約を使用してフィールドの値を確認できます。keywordフィールドの場合、terms aggregationを使用してフィールドの最も一般的な値を取得できます:

Python

  1. resp = client.search(
  2. index="my-index-000001",
  3. filter_path="aggregations",
  4. size=0,
  5. aggs={
  6. "top_values": {
  7. "terms": {
  8. "field": "my-field",
  9. "size": 10
  10. }
  11. }
  12. },
  13. )
  14. print(resp)

Ruby

  1. response = client.search(
  2. index: 'my-index-000001',
  3. filter_path: 'aggregations',
  4. body: {
  5. size: 0,
  6. aggregations: {
  7. top_values: {
  8. terms: {
  9. field: 'my-field',
  10. size: 10
  11. }
  12. }
  13. }
  14. }
  15. )
  16. puts response

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. filter_path: "aggregations",
  4. size: 0,
  5. aggs: {
  6. top_values: {
  7. terms: {
  8. field: "my-field",
  9. size: 10,
  10. },
  11. },
  12. },
  13. });
  14. console.log(response);

コンソール

  1. GET /my-index-000001/_search?filter_path=aggregations
  2. {
  3. "size": 0,
  4. "aggs": {
  5. "top_values": {
  6. "terms": {
  7. "field": "my-field",
  8. "size": 10
  9. }
  10. }
  11. }
  12. }

数値フィールドの場合、stats aggregationを使用してフィールドの値の分布を把握できます:

Python

  1. resp = client.search(
  2. index="my-index-000001",
  3. filter_path="aggregations",
  4. aggs={
  5. "my-num-field-stats": {
  6. "stats": {
  7. "field": "my-num-field"
  8. }
  9. }
  10. },
  11. )
  12. print(resp)

Ruby

  1. response = client.search(
  2. index: 'my-index-000001',
  3. filter_path: 'aggregations',
  4. body: {
  5. aggregations: {
  6. "my-num-field-stats": {
  7. stats: {
  8. field: 'my-num-field'
  9. }
  10. }
  11. }
  12. }
  13. )
  14. puts response

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. filter_path: "aggregations",
  4. aggs: {
  5. "my-num-field-stats": {
  6. stats: {
  7. field: "my-num-field",
  8. },
  9. },
  10. },
  11. });
  12. console.log(response);

コンソール

  1. GET my-index-000001/_search?filter_path=aggregations
  2. {
  3. "aggs": {
  4. "my-num-field-stats": {
  5. "stats": {
  6. "field": "my-num-field"
  7. }
  8. }
  9. }
  10. }

フィールドが値を返さない場合、データ取り込みプロセスを確認してください。フィールドには異なる名前が付けられている可能性があります。

最新の値を確認する

時系列データの場合、試みた時間範囲内にフィルタリングされていないデータが存在することを確認します。たとえば、@timestampフィールドの最新データをクエリしようとしている場合、次のコマンドを実行して、最大@timestampが試みた範囲内にあるかどうかを確認します:

Python

  1. resp = client.search(
  2. index="my-index-000001",
  3. sort="@timestamp:desc",
  4. size="1",
  5. )
  6. print(resp)

Ruby

  1. response = client.search(
  2. index: 'my-index-000001',
  3. sort: '@timestamp:desc',
  4. size: 1
  5. )
  6. puts response

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. sort: "@timestamp:desc",
  4. size: 1,
  5. });
  6. console.log(response);

コンソール

  1. GET my-index-000001/_search?sort=@timestamp:desc&size=1

クエリを検証、説明、プロファイルする

クエリが予期しない結果を返す場合、Elasticsearchはその理由を調査するためのいくつかのツールを提供します。

validate APIを使用して、クエリを検証できます。rewriteパラメータを使用して、Elasticsearchクエリが書き換えられるLuceneクエリを返します:

Python

  1. resp = client.indices.validate_query(
  2. index="my-index-000001",
  3. rewrite=True,
  4. query={
  5. "match": {
  6. "user.id": {
  7. "query": "kimchy",
  8. "fuzziness": "auto"
  9. }
  10. }
  11. },
  12. )
  13. print(resp)

Ruby

  1. response = client.indices.validate_query(
  2. index: 'my-index-000001',
  3. rewrite: true,
  4. body: {
  5. query: {
  6. match: {
  7. 'user.id' => {
  8. query: 'kimchy',
  9. fuzziness: 'auto'
  10. }
  11. }
  12. }
  13. }
  14. )
  15. puts response

Js

  1. const response = await client.indices.validateQuery({
  2. index: "my-index-000001",
  3. rewrite: "true",
  4. query: {
  5. match: {
  6. "user.id": {
  7. query: "kimchy",
  8. fuzziness: "auto",
  9. },
  10. },
  11. },
  12. });
  13. console.log(response);

コンソール

  1. GET /my-index-000001/_validate/query?rewrite=true
  2. {
  3. "query": {
  4. "match": {
  5. "user.id": {
  6. "query": "kimchy",
  7. "fuzziness": "auto"
  8. }
  9. }
  10. }
  11. }

explain APIを使用して、特定のドキュメントがクエリに一致する理由または一致しない理由を確認します:

Python

  1. resp = client.explain(
  2. index="my-index-000001",
  3. id="0",
  4. query={
  5. "match": {
  6. "message": "elasticsearch"
  7. }
  8. },
  9. )
  10. print(resp)

Ruby

  1. response = client.explain(
  2. index: 'my-index-000001',
  3. id: 0,
  4. body: {
  5. query: {
  6. match: {
  7. message: 'elasticsearch'
  8. }
  9. }
  10. }
  11. )
  12. puts response

Js

  1. const response = await client.explain({
  2. index: "my-index-000001",
  3. id: 0,
  4. query: {
  5. match: {
  6. message: "elasticsearch",
  7. },
  8. },
  9. });
  10. console.log(response);

コンソール

  1. GET /my-index-000001/_explain/0
  2. {
  3. "query" : {
  4. "match" : { "message" : "elasticsearch" }
  5. }
  6. }

profile APIは、検索リクエストに関する詳細なタイミング情報を提供します。結果の視覚的表現には、KibanaのSearch Profilerを使用します。

Kibanaでクエリのトラブルシューティングを行うには、ツールバーのInspectを選択します。次に、Requestを選択します。これで、KibanaがElasticsearchに送信したクエリをコピーして、コンソールでさらに分析できます。

インデックス設定を確認する

Index settingsは、検索結果に影響を与える可能性があります。たとえば、クエリが明示的なフィールドを指定しない場合にクエリされるフィールドを決定するindex.query.default_field設定があります。get index settings APIを使用して、インデックスの設定を取得します:

Python

  1. resp = client.indices.get_settings(
  2. index="my-index-000001",
  3. )
  4. print(resp)

Ruby

  1. response = client.indices.get_settings(
  2. index: 'my-index-000001'
  3. )
  4. puts response

Js

  1. const response = await client.indices.getSettings({
  2. index: "my-index-000001",
  3. });
  4. console.log(response);

コンソール

  1. GET /my-index-000001/_settings

動的インデックス設定は、update index settings APIを使用して更新できます。データストリームの動的インデックス設定を変更するには、データストリームによって使用されるインデックステンプレートを変更する必要があります。

静的設定の場合、正しい設定で新しいインデックスを作成する必要があります。次に、そのインデックスにデータを再インデックスできます。データストリームの場合は、データストリームの静的インデックス設定を変更するを参照してください。

遅いクエリを見つける

Slow logsは、遅いパフォーマンスの検索リクエストを特定するのに役立ちます。その上で、audit loggingを有効にすると、クエリのソースを特定するのに役立ちます。elasticsearch.yml設定ファイルに次の設定を追加して、クエリをトレースします。結果のログは冗長であるため、トラブルシューティングを行っていないときはこれらの設定を無効にしてください。

Yaml

  1. xpack.security.audit.enabled: true
  2. xpack.security.audit.logfile.events.include: _all
  3. xpack.security.audit.logfile.events.emit_request_body: true

Advanced tuning: finding and fixing slow Elasticsearch queriesを参照して、詳細情報を確認してください。