Java時間移行ガイド
Elasticsearchは7.0でjoda timeからjava timeに切り替え、日付関連の解析、フォーマット、および計算を行います。このガイドは、クラスターが影響を受けるかどうかを判断し、影響を受ける場合はアップグレードの準備をするのに役立つように設計されています。
日付フォーマットの変換
Elasticsearch 8にアップグレードするには、joda-timeの日付フォーマットをjava-timeの同等のものに変換する必要があります。
影響を受ける機能
java timeへの切り替えは、カスタムdate
およびdate_nanos
フォーマットにのみ影響します。
これらのフォーマットは、以下で一般的に使用されます:
カスタム日付フォーマットを使用していない場合は、このガイドの残りをスキップできます。ほとんどのカスタム日付フォーマットは互換性があります。ただし、いくつかは更新が必要です。
日付フォーマットが影響を受けるかどうかを確認するには、非推奨情報APIまたはKibanaアップグレードアシスタントを使用してください。
互換性のない日付フォーマット
以下のjoda-timeリテラルを含むカスタム日付フォーマットは移行する必要があります。
Y
(時代の年)y
に置き換えます。
例:YYYY-MM-dd
はyyyy-MM-dd
に変わるべきです。
java timeでは、Y
は週ベースの年に使用されます。Y
をy
の代わりに使用すると、年の計算でオフバイワンエラーが発生する可能性があります。
パターンYYYY-ww
と日付2019-01-01T00:00:00.000Z
は2019-01
を返します。パターンYYYY-ww
と日付2018-12-31T00:00:00.000Z
は2019-01
を返します(直感に反する)なぜなら、2019年のその週には4日以上あるからです。y
(年)u
に置き換えます。
例:yyyy-MM-dd
はuuuu-MM-dd
に変わるべきです。
java timeでは、y
は時代の年に使用されます。u
は非正の値を含むことができ、y
は含むことができません。y
は時代フィールドに関連付けることもできます。C
(時代の世紀)- java timeでは時代の世紀はサポートされていません。置き換えはありません。代わりに、入力を前処理することをお勧めします。
x
(週の年)Y
に置き換えます。
java timeでは、x
はゾーンオフセットを意味します。x
(週の年)をY
に適切に変換しないと、データ損失が発生する可能性があります。Z
(ゾーンオフセット/ID)- 複数の
X
に置き換えます。Z
はjava timeで似た意味を持ちます。ただし、java timeは異なる形式を解析するために異なる数のリテラルを期待します。
java timeでは、これらすべての日付を単一のフォーマットで解析することはできません。代わりに、3つの別々のフォーマットを指定する必要があります:``````bash
2010-01-01T01:02:03Z
2010-01-01T01:02:03+01
2010-01-01T01:02:03+01:02
2010-01-01T01:02:03+01:02:03
`
``````bash
2010-01-01T01:02:03Z
2010-01-01T01:02:03+01
both parsed with yyyy-MM-dd’T’hh:mm:ssX
2010-01-01T01:02:03+01:02
yyyy-MM-dd’T’hh:mm:ssXXX
2010-01-01T01:02:03+01:02:03
yyyy-MM-dd’T’hh:mm:ssXXXXX
フォーマットは`````||`````を使用して区切る必要があります:
#### テキスト
``````txt
yyyy-MM-dd'T'hh:mm:ssX||yyyy-MM-dd'T'hh:mm:ssXXX||yyyy-MM-dd'T'hh:mm:ssXXXXX
パターンがコロンなしで発生することを期待する場合も同様です(:
):たとえば、YYYY-MM-dd'T'hh:mm:ssZ
フォーマットは次の日付形式を受け入れます:
2010-01-01T01:02:03Z
2010-01-01T01:02:03+01
2010-01-01T01:02:03+0102
2010-01-01T01:02:03+010203
これらすべての形式をjava timeで受け入れるには、||
区切り文字を使用する必要があります:
テキスト
yyyy-MM-dd'T'hh:mm:ssX||yyyy-MM-dd'T'hh:mm:ssXX||yyyy-MM-dd'T'hh:mm:ssXXXX
d
(日)- java timeでは、
d
は依然として「日」として解釈されますが、柔軟性は低くなります。
たとえば、joda-timeの日付フォーマットYYYY-MM-dd
は2010-01-01
または2010-01-1
を受け入れます。
java timeでは、||
区切り文字を使用して各フォーマットを指定する必要があります:
テキスト
yyyy-MM-dd||yyyy-MM-d
java timeでは、d
は2桁以上を受け入れません。2桁以上の日を受け入れるには、java-timeの日付フォーマットにテキストリテラルを含める必要があります。たとえば、2010-01-00001
を解析するには、次のjava-timeの日付フォーマットを使用する必要があります:
テキスト
yyyy-MM-'000'dd
e
(曜日の名前)- java timeでは、
e
は依然として「曜日の名前」として解釈されますが、短縮形や完全なテキスト形式を解析しません。
たとえば、joda-timeの日付フォーマットEEE YYYY-MM
はWed 2020-01
とWednesday 2020-01
の両方を受け入れます。
これらの両方の日付をjava timeで受け入れるには、||
区切り文字を使用して各フォーマットを指定する必要があります:
テキスト
cccc yyyy-MM||ccc yyyy-MM
joda-timeリテラルE
は「週の日」として解釈されます。java-timeリテラルc
は「ローカライズされた週の日」として解釈されます。E
はWednesday
のような完全なテキストの日形式を受け入れません。
EEEE
および類似のテキスト形式- 完全なテキスト形式のサポートは、Java Development Kit (JDK)と他の実装の詳細に提供されるロケールデータに依存します。アップグレード前に、これらのパターンを含むフォーマットを慎重にテストすることをお勧めします。
z
(タイムゾーンテキスト)- java timeでは、
z
はUTCタイムゾーンが与えられた場合にZを出力します。
データでテスト
本番環境にデプロイする前に、実際のデータを使用して日付フォーマットの変更をテストすることを強くお勧めします。
インデックスマッピングの更新
インデックスマッピング内のjoda-timeの日付フォーマットを更新するには、更新されたマッピングを持つ新しいインデックスを作成し、データを再インデックスする必要があります。
以下のmy-index-000001
インデックスには、datetime
フィールドのマッピングと、カスタムjoda-time日付フォーマットを持つdate
フィールドが含まれています。
Python
resp = client.indices.get_mapping(
index="my-index-000001",
)
print(resp)
Ruby
response = client.indices.get_mapping(
index: 'my-index-000001'
)
puts response
Js
const response = await client.indices.getMapping({
index: "my-index-000001",
});
console.log(response);
コンソール
GET my-index-000001/_mapping
コンソール結果
{
"my-index-000001" : {
"mappings" : {
"properties" : {
"datetime": {
"type": "date",
"format": "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis"
}
}
}
}
}
たとえば、以下の`````my-index-000002`````インデックスは`````datetime`````フィールドの日付フォーマットを`````uuuu/MM/dd HH:mm:ss||uuuu/MM/dd||epoch_millis`````に変更します。
#### Python
``````python
resp = client.indices.create(
index="my-index-000002",
mappings={
"properties": {
"datetime": {
"type": "date",
"format": "uuuu/MM/dd HH:mm:ss||uuuu/MM/dd||epoch_millis"
}
}
},
)
print(resp)
`
Ruby
response = client.indices.create(
index: 'my-index-000002',
body: {
mappings: {
properties: {
datetime: {
type: 'date',
format: 'uuuu/MM/dd HH:mm:ss||uuuu/MM/dd||epoch_millis'
}
}
}
}
)
puts response
Js
const response = await client.indices.create({
index: "my-index-000002",
mappings: {
properties: {
datetime: {
type: "date",
format: "uuuu/MM/dd HH:mm:ss||uuuu/MM/dd||epoch_millis",
},
},
},
});
console.log(response);
コンソール
PUT my-index-000002
{
"mappings": {
"properties": {
"datetime": {
"type": "date",
"format": "uuuu/MM/dd HH:mm:ss||uuuu/MM/dd||epoch_millis"
}
}
}
}
次に、古いインデックスから新しいインデックスにデータを再インデックスします。
以下の再インデックスAPIリクエストは、my-index-000001
からmy-index-000002
にデータを再インデックスします。
Python
resp = client.reindex(
source={
"index": "my-index-000001"
},
dest={
"index": "my-index-000002"
},
)
print(resp)
Ruby
response = client.reindex(
body: {
source: {
index: 'my-index-000001'
},
dest: {
index: 'my-index-000002'
}
}
)
puts response
Js
const response = await client.reindex({
source: {
index: "my-index-000001",
},
dest: {
index: "my-index-000002",
},
});
console.log(response);
コンソール
POST _reindex
{
"source": {
"index": "my-index-000001"
},
"dest": {
"index": "my-index-000002"
}
}
インデックスエイリアスを使用している場合は、それらを新しいインデックスを指すように更新します。
Python
resp = client.indices.update_aliases(
actions=[
{
"remove": {
"index": "my-index-000001",
"alias": "my-index"
}
},
{
"add": {
"index": "my-index-000002",
"alias": "my-index"
}
}
],
)
print(resp)
Js
const response = await client.indices.updateAliases({
actions: [
{
remove: {
index: "my-index-000001",
alias: "my-index",
},
},
{
add: {
index: "my-index-000002",
alias: "my-index",
},
},
],
});
console.log(response);
コンソール
POST /_aliases
{
"actions" : [
{ "remove" : { "index" : "my-index-000001", "alias" : "my-index" } },
{ "add" : { "index" : "my-index-000002", "alias" : "my-index" } }
]
}