2017-11-01 8 views
1

名前に '。'が含まれているため、名前を変更する必要があるelasticsearch(5.5.1)のフィールドがあります。様々な問題を引き起こしています。名前を変更したいフィールドは、別のフィールドの中にネストされています。elasticsearch rename processorとingest pipelineでドットを含むネストされたフィールドの名前を変更する方法

私がここで説明するように再インデックスを実行するためにインジェストパイプラインで名前の変更プロセッサを使用しようとしています

:ここhttps://stackoverflow.com/a/43142634/5114

は私のパイプラインのシミュレーション要求である(あなたがテストするKibanaにおける開発ツール・ユーティリティにそのままこれをコピーすることができますそれは):私が思う

{ 
    "docs": [ 
    { 
     "error": { 
     "root_cause": [ 
      { 
      "type": "exception", 
      "reason": "java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: field [message.message.group1] doesn't exist", 
      "header": { 
       "processor_type": "rename" 
      } 
      } 
     ], 
     "type": "exception", 
     "reason": "java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: field [message.message.group1] doesn't exist", 
     "caused_by": { 
      "type": "illegal_argument_exception", 
      "reason": "java.lang.IllegalArgumentException: field [message.message.group1] doesn't exist", 
      "caused_by": { 
      "type": "illegal_argument_exception", 
      "reason": "field [message.message.group1] doesn't exist" 
      } 
     }, 
     "header": { 
      "processor_type": "rename" 
     } 
     } 
    } 
    ] 
} 

POST _ingest/pipeline/_simulate 
{ 
    "pipeline" : { 
     "description": "rename nested fields to remove dot", 
      "processors": [ 
      { 
       "rename" : { 
        "field" : "message.message.group1", 
        "target_field" : "message_group1" 
       } 
      }, 
      { 
       "rename" : { 
        "field" : "message.message.group2", 
        "target_field" : "message.message_group2" 
       } 
      } 
      ] 
    }, 
    "docs":[ 
     { 
      "_type": "status", 
      "_id": "1509533940000-m1-bfd7183bf036bd346a0bcf2540c05a70fbc4d69e", 
      "_version": 5, 
      "_score": null, 
      "_source": { 
       "message": { 
        "_job-id": "AV8wHJEaa4J0sFOfcZI5", 
        "message.group1": 0, 
        "message.group2": "foo" 
       }, 
       "timestamp": 1509533940000 
      } 
     } 
    ] 
} 

問題は私のパイプラインを使用しようとすると、私はエラーを取得するということです問題は、フィールド "message.group1"が別のフィールド( "メッセージ")の内側にあることによって発生します。私は、プロセッサの文脈で私が望む分野をどのように参照するのか分かりません。ネストされたフィールド、ドットを含むフィールド、およびドットを含むネストされたフィールドの間にはあいまいさがあるようです。

これらのフィールドを参照する正しい方法、またはElasticsearchが必要な処理を実行できない場合は、これが不可能であることを確認しています。 Elasticsearchがこれを行うことができれば、おそらく非常に速くなるでしょう。そうしないと、文書を取り込み、変換して新しいインデックスに保存する外部スクリプトを書く必要があります。

+0

似たようなことを話す古い質問があります:https://stackoverflow.com/questions/36774110/replacing-a-dot-in-an-field-name – Mnebuerquo

答えて

0

私がElasticsearchコードで調べてみると、なぜこれがうまくいかないのか分かります。

我々はElasticsearch名前の変更プロセッサを見てまず: https://github.com/elastic/elasticsearch/blob/9eff18374d68355f6acb58940a796268c9b6f2de/modules/ingest-common/src/main/java/org/elasticsearch/ingest/common/RenameProcessor.java#L76-L84

Object value = document.getFieldValue(field, Object.class); 
document.removeField(field); 
try { 
    document.setFieldValue(targetField, value); 
} catch (Exception e) { 
    // setting the value back to the original field shouldn't as we just fetched it from that field: 
    document.setFieldValue(field, value); 
    throw e; 
} 

これが何をやっていることは、フィールドを削除し、それを新しいフィールドを追加し、その後、その値を取得し、名前を変更するフィールドを探しています新しい名前を使用しています。

今、私たちはdocument.getFieldValueで何が起こるかを見て: https://github.com/elastic/elasticsearch/blob/9eff18374d68355f6acb58940a796268c9b6f2de/core/src/main/java/org/elasticsearch/ingest/IngestDocument.java#L101-L108

public <T> T getFieldValue(String path, Class<T> clazz) { 
    FieldPath fieldPath = new FieldPath(path); 
    Object context = fieldPath.initialContext; 
    for (String pathElement : fieldPath.pathElements) { 
     context = resolve(pathElement, path, context); 
    } 
    return cast(path, context, clazz); 
} 

は、文書内のフィールドへのパスを表すためにFieldPathオブジェクトを使用しています注意してください。

は今FieldPathがパスを表す方法を見て: "" https://github.com/elastic/elasticsearch/blob/9eff18374d68355f6acb58940a796268c9b6f2de/core/src/main/java/org/elasticsearch/ingest/IngestDocument.java#L688

this.pathElements = newPath.split("\\."); 

これは、任意の上のパスを分割していますなぜなら、これはフィールド名のパス要素間の区切り文字であるからです。

問題は、ソースドキュメントに「message.group1」という名前のフィールドがあることです。そのため、参照できるようにする必要があります。パスを "。"で分割するだけです"。"を含むフィールド名は考慮しません。名前に。 javascriptのような構文が必要になります。ここでは、括弧と引用符を使用してドットの意味を異なるものにすることができます。

ソースドキュメントがすべて変換され、 "。"フィールド名にフィールドを保存する前にオブジェクトに変換すると、このパススキームが機能します。しかし、フィールド名に "。"が含まれているソース文書では、我々は特定の状況でそれらを参照することはできません。

私の問題を解決しインデックスを再インデックスするために、私は文書のバッチを取り出し、それらを変換し、それらを新しいインデックスにバルク挿入したPythonスクリプトを書いた。これは基本的にElasticsearch reindex apiの機能ですが、代わりにPythonで行いました。

関連する問題