Elasticsearchのdate型へのOracle NoSQLのTIMESTAMPのマッピング

日時を表す値がOracle NoSQL表のフィールドに書き込まれる場合、値はjava.sql.Timestampのインスタンスとして表に格納されます。これは、Oracle NoSQLのtimestamp enum型に対応します。SQLリファレンス・ガイドアトミック・データ型を参照してください。

この場合、表の作成時に、キーワードtimestampを使用して、表にこのようなフィールドを指定します。timestampキーワードとともに、次の形式の宣言を使用して、値を格納するときに適用するprecisionを表すintegerパラメータも指定する必要があります。

TIMESTAMP(<precision>)

precisionに入力される値は、0から9の10個の有効なinteger値の1つである必要があります。一般に、Oracle NoSQL Databaseで定義されるtimestampデータ型では、粒度が細かい単位の時間精度を表に格納できます(ナノ秒単位まで)。precisionの値に0を入力すると、timestamp値の精度が最も低い表現を指定したことになります。これは値の秒コンポーネントの小数点以下の桁数が0の、yyyy-MM-dd'T'HH:mm:ssの形式に対応します。値9では、指定された日のナノ秒までの正確さの瞬間を含む、最も細かい粒度の(つまり、精度が最も高い)表現を指定したことになります。ナノ秒の精度のtimestamp値は、秒コンポーネントの小数点以下の桁数が9の、yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSの形式に対応します。他のすべての精度(1–8)は、最も低い精度(小数点以下の桁数が0)と最も高い精度(小数点以下の桁数が9)の間のいずれかの精度に該当する日時の粒度を表します。

別の具体的な例として、表の主キーを含むidフィールドと、秒コンポーネントで小数点以下6桁の精度で表される日付と時刻を表す値(例: date = 1998-10-26, time-of-day = 08:33:59.735978)を含むtsという名前のフィールドで構成されるtsTableという表を作成するとします。このような表を作成するには、管理CLIから次のコマンドを実行します。

kv-> execute 'CREATE TABLE tsTable (id INTEGER, ts TIMESTAMP(6), PRIMARY KEY (id))';

ここで、tsフィールドに次の値を格納するとします。

tsVal[0] = 1996-12-31T23:01:43.987654321
tsVal[1] = 2005-03-20T14:10:25.258
tsVal[2] = 1998-10-26T08:33:59.735978
tsVal[3] = 2001-09-15T23:01:43.55566677
tsVal[4] = 2002-04-06T17:07:38.7653459

これらの値を格納するには、次のようなコードを実行します。

final KVStore store = KVStoreFactory.getStore 
    (new KVStoreConfig(<storeName>, <host> + ":" + <port>));
final TableAPI tableAPI = store.getTableAPI();
final Tabletable = tableAPI.getTable("tsTable");
for (int i = 0; i < 5; i++) {
    final Row row = table.createRow();
    row.put(id, i);
    row.put(ts, TimestampUtils.parseString(tsVal[i]));
    tableAPI.putIfAbsent(row, null, null); 
}

表のtsフィールドは精度6で作成されているため、各値は、値の秒コンポーネントの小数点以下の桁数が6として格納されます。具体的には、格納される値の小数点以下の桁数が6より多い場合、Oracle NoSQLは、秒コンポーネントの小数点以下の部分が小数点第6位に丸められた値を格納します。たとえば、前述のリストのtsVal[4]は、2002-04-06T17:07:38.765346として格納されます。

同様に、格納される値の小数点以下の桁数が6より少ない場合、Oracle NoSQLは、秒コンポーネントの小数点以下の部分をゼロで埋めます。たとえば、前述のリストのtsVal[1]は、2005-03-20T14:10:25.258000として格納されます。

timestamp値を含む表のフィールドに対してテキスト索引を作成する場合は、前述のようなフィールドに対するOracle NoSQL Database表APIの処理方法を理解することが重要です。これは、Elasticsearchが、Oracle NoSQL Databaseで格納されるjava.sql.Timestamp型に直接マップされないElasticsearchのdate型を使用して日時を表す値を格納するため、重要です。

全文検索のtimestampフィールドに索引付けする場合、CREATE FULLTEXT INDEXコマンドにElasticsearchのdate型を指定する必要があります。指定しないと、Elasticsearchによって、フィールドの値がstring型として処理されます。たとえば、前述の例のtsTabletsフィールドに対して、最も単純に(全文検索用に)索引付けするには、次のコマンドを実行します。

kv-> execute 'CREATE FULLTEXT INDEX tsIndex ON tsTable (ts{"type":"date"})';

この場合は、索引付けされる値を処理する際にdate型の形式の最大限の範囲を処理するようElasticsearchに通知する、デフォルトのマッピング仕様が生成されます。

Elasticsearchで日時を表す値に索引付けする場合、それらの値にdate型を指定するときは常に、各索引付き値が準拠する必要がある形式を指定することもできます。ここで、指定した値が指定の形式を満たさない場合はエラーが発生します。Elasticsearchの日付を参照してください。Elasticsearch APIは、string値にanalyzerを指定する方法と同様に、マッピング仕様を介して、date型の指定値に索引付けするときにElasticsearchで予期される形式の指定に使用できる、formatパラメータを定義します。具体的には、次のようになります。

<fieldname>{"type":"date","format":"<format>"}

formatトークンに入力される値は、明示的な形式(yyyy-MM-dd'T'HH:mm:ssなど)にすることも、Elasticsearchの事前定義済の1つ以上の値(マクロ)の組合せにすることもできます。Elasticsearchの組込みの形式を参照してください。

Elasticsearch API (Oracle NoSQLではない)を使用する場合、date型に対する通常のElasticsearchマッピング仕様では、次のように、Elasticsearchの組込みの形式のセットからの1つ以上の値とともに、明示的な形式を指定できます。

{"type":"date","format":"yyyy-MM-dd'T'HH:mm:ss.SSS||yyyy-MM-dd||epoch_millis"}

示されているような形式で、1997-11-17T08:33:59.7351997-11-17などの形式で、またはエポック以降のミリ秒数として値を予期するようElasticsearchに通知されます。値にその他の形式が使用されている場合、エラーが発生し、Elasticsearchは値に索引付け(格納)しません。

前述の例で示したような明示的な形式を使用するのではなく、次のように、表のマクロのみのなんらかの組合せを使用して、形式を指定することもできます。

{"type":"date","format":"strict_date_optional_time||epoch_millis"}

これにより、Elasticsearchに対して、受け入れ可能な日付値には日付(strict_date=yyyy-MM-dd)が含まれる必要があるものの、Elasticsearchは時刻コンポーネント(optional_time)の有無に関係なくすべての値を受け入れる必要があることが通知されます。さらに、値がエポック以降のミリ秒数を表す場合、その値もElasticsearchによって受け入れられる必要があります。

CREATE FULLTEXT INDEXコマンドを使用して、全文検索用にtimestamp値に索引付けすることに関しては、前述のElasticsearch APIの例と同様の方法でdateフィールドにElasticsearchのformatパラメータを指定できますが、あまり実用的ではありません。まず、Elasticsearchの組込みの形式のセットからのマクロの有効な組合せの数は非常に大きく、ユーザーにとって大きな負担となることがあります。

次に、Elasticsearchによって定義された他のマッピング・パラメータ(たとえば、string型のanalyzerパラメータ)とは異なり、ユーザーがElasticsearchのdateフィールドに有効な形式を指定する場合、索引付けされる値の1つ以上がその形式を満たさないと、(Elasticsearchで)エラーが発生し、それらの値は索引付けされません。たとえば、ユーザーがstringフィールドにフランス語のアナライザを指定したが、実際には値が英語である場合、予期しない検索出力になりますが、エラーは発生しません。一方、ユーザーがdateフィールドにyyyy-MM-dd'T'HH:mm:ss.SSSという形式を指定したが、索引付けの対象となる値の秒コンポーネントの小数点以下の桁数が3を超える場合は、索引は作成されますが、形式エラーが発生して、準拠しない値には索引付けされません。

date値の形式を指定するためのより便利なメカニズムを提供し、前述の種類の形式エラーの発生を最小化するために、CREATE FULLTEXT INDEXコマンドには特別な"name":"value"パラメータが定義されています。Elasticsearchのformatパラメータ(およびその有効な値)を使用するのではなく、Oracle NoSQLのtimestamp値をElasticsearchでdate値として索引付けする場合、特別に定義されたprecisionパラメータをかわりに使用する必要があります。precisionパラメータはオプションですが、CREATE FULLTEXT INDEXコマンドで"type":"date"を指定して使用する場合は、そのパラメータの値はmillisまたはnanosのいずれかになります。具体的には、CREATE FULLTEXT INDEXコマンドを使用して、NoSQLのtimestamp値をElasticsearchでdate値として索引付けする場合、そのコマンドに次のパラメータ・マッピングの1つを指定する必要があります。

  • {"type":"date"}
  • {"type":"date","precision":"millis"}
  • {"type":"date","precision":"nanos"}

デフォルトのprecision (つまりno precision)とnanos precisionの両方では、Elasticsearchでのエラーなしで、timestamp形式の最大限の範囲が、有効なdate型としてマップおよび索引付けされます。一方、millis precisionでは、精度が3以下で定義されたtimestamp値にのみ索引付けされます。そのため、使用する精度は次の基準に基づく必要があります。

  • 索引付け対象の表フィールドのすべての値の精度が3 (ミリ秒)以下のみであることが確実で、すべての場合に小数点以下の桁数3を使用して値に索引付けする場合は、millis precisionを指定します。
  • 索引付け対象のフィールドが可変精度のtimestamp値で構成されているとき、精度が3以下の値にのみ索引付けする場合は、millis precisionを指定し、ミリ秒より大きい精度の値に索引付けされないようにします。
  • それ以外の場合は、nanos precisionまたはデフォルトのprecisionを使用します。

要約すると、特別なprecisionパラメータによって、ユーザーがdate型に指定できる値の数が最小化されるだけでなく、そのような値を有効な形式の最大限の範囲にマップし、索引でのミリ秒精度をユーザーが適用できるようにする方法を提供することで、形式エラーの発生も減少します。

注意:

前述のとおり、date型に対して指定されたnanosの精度は、現在、no precisionを指定することと同じで、これによってデフォルトのdate形式に変換されます。これは冗長に見えますが、2つの理由でnanosオプションが定義されています。1つ目は、millisオプションの対称となることを目的としています。これにより、索引付けされるtimestampフィールドがミリ秒を超える精度の値で構成されていることをユーザーが認識している場合に、単純にnanosを指定でき、Elasticsearchに登録されるマッピング仕様を構成するときに正しい処理が行われます。

nanosオプションを定義する2つ目の理由は、Elasticsearchで、現在、ミリ秒を超える精度の形式がサポートされていないことに関連しています。(Elasticsearchの組込みの形式には、millisを超える精度に関連付けられたマクロがないことに注意してください)。今後、ナノ秒の精度を含む形式をサポートするElasticsearchのバージョンがリリースされた場合は、Oracle NoSQL Databaseで非常に簡単な変更を加えることで、現在のnanosオプションを、Elasticsearchで定義される新しい形式にマップできます。公開APIの変更や、ユーザー・アプリケーションに対する変更は必要ありません。