Logstashを使ったElasticsearchの再インデックス(日本語訳)

Posted by johtani on Tuesday, May 26, 2015

目次

※この記事は次のブログを翻訳したものになります。

原文:Reindex Elasticsearch With Logstash

Thanks David!

マッピングを変更したり、インデックスの設定を変更したり、あるサーバから他のサーバや、 あるクラスタから他のクラスタ(例えば複数のデータセンターのような場合)にデータを再インデックスしたくなることがあるでしょう。

後者のような場合はSnapshotやRestoreの機能を利用することもできますが、インデックスの設定を変更をしたい場合は その他の方法が必要になります。

Logstash 1.5.0で、 elasticsearch inputelasticsearch outputを使うことで、とても簡単に再インデックスができます。

ではやってみましょう。

古いクラスタ

elasticsearch 1.5.2 はすでにダウンロード済みとして、localhost:9200oldという名前のクラスタを起動します。

bin/elasticsearch --cluster.name=old

クラスタにpersonという名前のインデックスが存在します。 これは、5シャードで、100万件のドキュメントを持っています。

新しいクラスタ

次に新しいクラスタを起動します。 localhost:9201newという名前のクラスタを起動します。

bin/elasticsearch --cluster.name=new

こちらは、空です。

curl -XGET "http://localhost:9201/person"
{
   "error": "IndexMissingException[[person] missing]",
   "status": 404
}

Logstashのインストール

次に、Logstash 1.5.0をダウンロードして、インストールします。

wget http://download.elastic.co/logstash/logstash/logstash-1.5.0.tar.gz
tar xzf logstash-1.5.0.tar.gz
cd logstash-1.5.0

logstashの設定ファイルlogstash.confを次のように設定します。

input {
  # We read from the "old" cluster
  elasticsearch {
    hosts => [ "localhost" ]
    port => "9200"
    index => "person"
    size => 500
    scroll => "5m"
    docinfo => true
  }
}

output {
  # We write to the "new" cluster
  elasticsearch {
    host => "localhost"
    port => "9201"
    protocol => "http"
    index => "%{[@metadata][_index]}"
    index_type => "%{[@metadata][_type]}"
    document_id => "%{[@metadata][_id]}"
  }
  # We print dots to see it in action
  stdout {
    codec => "dots"
  }
}

実行と修正

実行します。

bin/logstash -f logstash.conf

ドキュメントのチェックと修正

何が起きたでしょう?

curl -XGET "http://localhost:9200/person/person/AU1wqyQWZJKU8OibfxgH"
{
   "_index": "person",
   "_type": "person",
   "_id": "AU1wqyQWZJKU8OibfxgH",
   "_version": 1,
   "found": true,
   "_source": {
      "name": "Tali Elyne",
      "dateOfBirth": "1955-05-03",
      "gender": "female",
      "children": 2,
      "marketing": {
         "cars": null,
         "shoes": null,
         "toys": null,
         "fashion": null,
         "music": null,
         "garden": null,
         "electronic": null,
         "hifi": null,
         "food": 846
      },
      "address": {
         "country": "Germany",
         "zipcode": "0099",
         "city": "Bonn",
         "countrycode": "DE",
         "location": [
            7.075943707068682,
            50.72883500730124
         ]
      }
   }
}

もう一方のクラスタと比較してみましょう。

curl -XGET "http://localhost:9201/person/person/AU1wqyQWZJKU8OibfxgH"
{
   "_index": "person",
   "_type": "person",
   "_id": "AU1wqyQWZJKU8OibfxgH",
   "_version": 1,
   "found": true,
   "_source": {
      "name": "Tali Elyne",
      "dateOfBirth": "1955-05-03",
      "gender": "female",
      "children": 2,
      "marketing": {
         "cars": null,
         "shoes": null,
         "toys": null,
         "fashion": null,
         "music": null,
         "garden": null,
         "electronic": null,
         "hifi": null,
         "food": 846
      },
      "address": {
         "country": "Germany",
         "zipcode": "0099",
         "city": "Bonn",
         "countrycode": "DE",
         "location": [
            7.075943707068682,
            50.72883500730124
         ]
      },
      "@version": "1",
      "@timestamp": "2015-05-20T09:53:44.089Z"
   }
}

Logstashは@version@timestampフィールドを追加してしました。 これらを除去したいので、Mutate filter pluginremove_fieldを使います。

filter {
  mutate {
    remove_field => [ "@timestamp", "@version" ]
  }
}

マッピングのチェックと修正

実際に、logstashは_sourceフィールドを既存のドキュメントから読み込み、 それらを新しいクラスタに直接投入しています。 しかし、logstashはマッピングについてはケアしていません。

古いマッピングと新しいマッピングを比較するために、マッピングを取得してみましょう。

curl -XGET "http://localhost:9200/person/person/_mapping"
{
   "person": {
      "mappings": {
         "person": {
            "properties": {
               "address": {
                  "properties": {
                     "city": {
                        "type": "string",
                        "index": "not_analyzed"
                     },
                     "country": {
                        "type": "string",
                        "index": "not_analyzed"
                     },
                     "countrycode": {
                        "type": "string",
                        "index": "not_analyzed"
                     },
                     "location": {
                        "type": "geo_point"
                     },
                     "zipcode": {
                        "type": "string"
                     }
                  }
               },
               "children": {
                  "type": "long"
               },
               "dateOfBirth": {
                  "type": "date",
                  "format": "dateOptionalTime"
               },
               "gender": {
                  "type": "string",
                  "index": "not_analyzed"
               },
               "marketing": {
                  "properties": {
                     "cars": {
                        "type": "long"
                     },
                     "electronic": {
                        "type": "long"
                     },
                     "fashion": {
                        "type": "long"
                     },
                     "food": {
                        "type": "long"
                     },
                     "garden": {
                        "type": "long"
                     },
                     "hifi": {
                        "type": "long"
                     },
                     "music": {
                        "type": "long"
                     },
                     "shoes": {
                        "type": "long"
                     },
                     "toys": {
                        "type": "long"
                     }
                  }
               },
               "name": {
                  "type": "string"
               }
            }
         }
      }
   }
}
curl -XGET "http://localhost:9201/person/person/_mapping"
{
   "person": {
      "mappings": {
         "person": {
            "properties": {
               "address": {
                  "properties": {
                     "city": {
                        "type": "string"
                     },
                     "country": {
                        "type": "string"
                     },
                     "countrycode": {
                        "type": "string"
                     },
                     "location": {
                        "type": "double"
                     },
                     "zipcode": {
                        "type": "string"
                     }
                  }
               },
               "children": {
                  "type": "long"
               },
               "dateOfBirth": {
                  "type": "date",
                  "format": "dateOptionalTime"
               },
               "gender": {
                  "type": "string"
               },
               "marketing": {
                  "properties": {
                     "cars": {
                        "type": "long"
                     },
                     "electronic": {
                        "type": "long"
                     },
                     "fashion": {
                        "type": "long"
                     },
                     "food": {
                        "type": "long"
                     },
                     "garden": {
                        "type": "long"
                     },
                     "hifi": {
                        "type": "long"
                     },
                     "music": {
                        "type": "long"
                     },
                     "shoes": {
                        "type": "long"
                     },
                     "toys": {
                        "type": "long"
                     }
                  }
               },
               "name": {
                  "type": "string"
               }
            }
         }
      }
   }
}

これにより、いくつかの相違を発見できます。

 "location": {
    "type": "geo_point"
 }
 "location": {
    "type": "double"
 }

データをインデックスする「前」に、実際に利用したいマッピングでインデックスを作成しておくことで、 この問題に対処できます。 この時点で、オリジナルのマッピングを望んだ形に変更することができます。例えば、アナライザを変更したりです。 また、インデックスの設定を新しく定義することもできます。 デフォルトでは、Elasticsearchは5つのシャードと各シャードに対して1つのレプリカを作成します。 しかし、この時点でもう一度変更することが可能です。

curl -XDELETE "http://localhost:9201/person"
curl -XPUT "http://localhost:9201/person" -d'
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  }
}'
curl -XPUT "http://localhost:9201/person/person/_mapping" -d'
{
  "person": {
    "properties": {
      "address": {
        "properties": {
          "city": {
            "type": "string",
            "index": "not_analyzed"
          },
          "country": {
            "type": "string",
            "index": "not_analyzed"
          },
          "countrycode": {
            "type": "string",
            "index": "not_analyzed"
          },
          "location": {
            "type": "geo_point"
          },
          "zipcode": {
            "type": "string"
          }
        }
      },
      "children": {
        "type": "long"
      },
      "dateOfBirth": {
        "type": "date",
        "format": "dateOptionalTime"
      },
      "gender": {
        "type": "string",
        "index": "not_analyzed"
      },
      "marketing": {
        "properties": {
          "cars": {
            "type": "long"
          },
          "electronic": {
            "type": "long"
          },
          "fashion": {
            "type": "long"
          },
          "food": {
            "type": "long"
          },
          "garden": {
            "type": "long"
          },
          "hifi": {
            "type": "long"
          },
          "music": {
            "type": "long"
          },
          "shoes": {
            "type": "long"
          },
          "toys": {
            "type": "long"
          }
        }
      },
      "name": {
        "type": "string"
      }
    }
  }
}'

さて、もう一度再インデックスしましょう!

bin/logstash -f logstash.conf

インデックスやタイプ名の変更

もちろん、インデックス名やタイプ名、IDを変更したい場合も変更が可能です!:)

  elasticsearch {
    host => "localhost"
    port => "9201"
    protocol => "http"
    index => "europe_people"
    index_type => "someone"
    document_id => "%{[@metadata][_id]}"
  }

comments powered by Disqus

See Also by Hugo


Related by prelims-cli