TIMESTAMPTZ フィールドCompatible with Milvus 2.6.6+

eコマースシステム、コラボレーションツール、分散ロギングなど、複数の地域にまたがって時間を追跡するアプリケーションでは、タイムゾーンを含むタイムスタンプを正確に扱う必要があります。MilvusのTIMESTAMPTZ データ型は、タイムスタンプに関連するタイムゾーンを一緒に保存することで、この機能を提供します。

TIMESTAMPTZフィールドとは?

TIMESTAMPTZ フィールドは、Milvusにおけるスキーマ定義データ型(DataType.TIMESTAMPTZ )であり、タイムゾーンを考慮した入力を処理し、すべての時刻を内部的にUTC絶対時刻として格納します。

  • 許容される入力形式:タイムゾーンオフセットを含むISO 8601文字列(例:"2025-05-01T23:59:59+08:00" は、2025年5月1日 午後11時59分59秒(UTC+08:00)を表します)。

  • 内部保存:すべての `TIMESTAMPTZ ` 値は正規化され、協定世界時(UTC)で保存されます。

  • 比較およびフィルタリング:すべてのフィルタリングおよび並べ替え操作は UTC で行われるため、異なるタイムゾーン間でも一貫性があり、予測可能な結果が保証されます。

  • TIMESTAMPTZ フィールドのnullable=True を設定することで、欠損値を許可することができます。

  • default_value を使用して、ISO 8601形式のデフォルトのタイムスタンプ値を指定できます。

詳細については、「Nullable および Default」を参照してください。

基本的な操作

TIMESTAMPTZ フィールドを使用する基本的なワークフローは、Milvus の他のスカラーフィールドと同様です。フィールドの定義 → データの挿入 → クエリ/フィルタリング。

ステップ 1: TIMESTAMPTZ フィールドを定義する

TIMESTAMPTZ フィールドを使用するには、コレクションの作成時にコレクションスキーマ内で明示的に定義する必要があります。以下の例は、型がDataType.TIMESTAMPTZtsz フィールドを持つコレクションを作成する方法を示しています。

import time
from pymilvus import MilvusClient, DataType
import datetime
import pytz

server_address = "http://localhost:19530"
collection_name = "timestamptz_test123"

client = MilvusClient(uri=server_address)

if client.has_collection(collection_name):
    client.drop_collection(collection_name)

schema = client.create_schema()
# Add a primary key field
schema.add_field("id", DataType.INT64, is_primary=True)
# Add a TIMESTAMPTZ field that allows null values
schema.add_field("tsz", DataType.TIMESTAMPTZ, nullable=True)
# Add a vector field
schema.add_field("vec", DataType.FLOAT_VECTOR, dim=4)

client.create_collection(collection_name, schema=schema, consistency_level="Session")
print(f"Collection '{collection_name}' with a TimestampTz field created successfully.")
// java
// nodejs
// go
# restful

ステップ 2: データの挿入

タイムゾーンオフセットを含む ISO 8601 文字列を持つエンティティを挿入します。

以下の例では、8,193 行のサンプルデータをコレクションに挿入します。各行には以下が含まれます:

  • 一意のID

  • タイムゾーンを考慮したタイムスタンプ(上海時間)

  • 単純な4次元ベクトル

data_size = 8193

# Get the Asia/Shanghai time zone using the pytz library
# You can use any valid IANA time zone identifier such as:
#   "Asia/Tokyo", "America/New_York", "Europe/London", "UTC", etc.
# To view all available values:
#   import pytz; print(pytz.all_timezones)
# Reference:
#   IANA database – https://www.iana.org/time-zones
#   Wikipedia – https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
shanghai_tz = pytz.timezone("Asia/Shanghai")

data = [
    {
        "id": i + 1,
        "tsz": shanghai_tz.localize(
            datetime.datetime(2025, 1, 1, 0, 0, 0) + datetime.timedelta(days=i)
        ).isoformat(),
        "vec": [float(i) / 10 for i in range(4)],
    }
    for i in range(data_size)
]

client.insert(collection_name, data)
print("Data inserted successfully.")
// java
// nodejs
// go
# restful

ステップ 3: フィルタリング操作

TIMESTAMPTZ スカラー比較、区間演算、および時刻成分の抽出をサポートしています。

TIMESTAMPTZ フィールドに対してフィルタリング操作を実行する前に、以下の点を確認してください:

  • 各ベクトルフィールドにインデックスが作成されていること。

  • コレクションがメモリに読み込まれていること。

サンプルコードを表示

# Create index on vector field
index_params = client.prepare_index_params()
index_params.add_index(
    field_name="vec",
    index_type="AUTOINDEX",
    index_name="vec_index",
    metric_type="COSINE"
)
client.create_index(collection_name, index_params)
print("Index created successfully.")

# Load the collection
client.load_collection(collection_name)
print(f"Collection '{collection_name}' loaded successfully.")
// java
// nodejs
// go
# restful

タイムスタンプによるフィルタリングを含むクエリ

==!=<><=>= などの算術演算子を使用します。Milvus で利用可能な算術演算子の完全な一覧については、「算術演算子」を参照してください。

以下の例では、タイムスタンプ(tsz )が2025-01-03T00:00:00+08:00 ではないエンティティをフィルタリングしています:

# Query for entities where tsz is not equal to '2025-01-03T00:00:00+08:00'
expr = "tsz != ISO '2025-01-03T00:00:00+08:00'"

results = client.query(
    collection_name=collection_name,
    filter=expr,
    output_fields=["id", "tsz"],
    limit=10
)

print("Query result: ", results)

# Expected output:
# Query result:  data: ["{'id': 1, 'tsz': '2024-12-31T16:00:00Z'}", "{'id': 2, 'tsz': '2025-01-01T16:00:00Z'}", "{'id': 4, 'tsz': '2025-01-03T16:00:00Z'}", "{'id': 5, 'tsz': '2025-01-04T16:00:00Z'}", "{'id': 6, 'tsz': '2025-01-05T16:00:00Z'}", "{'id': 7, 'tsz': '2025-01-06T16:00:00Z'}", "{'id': 8, 'tsz': '2025-01-07T16:00:00Z'}", "{'id': 9, 'tsz': '2025-01-08T16:00:00Z'}", "{'id': 10, 'tsz': '2025-01-09T16:00:00Z'}", "{'id': 11, 'tsz': '2025-01-10T16:00:00Z'}"]
// java
// nodejs
// go
# restful

上記の例において、

  • tsz は、スキーマで定義されたTIMESTAMPTZ フィールド名です。

  • ISO '2025-01-03T00:00:00+08:00' は、タイムゾーンオフセットを含むISO 8601形式のタイムスタンプリテラルです。

  • != は、フィールドの値をそのリテラルと比較します。その他、サポートされている演算子には、==<<=> 、および>= があります。

間隔演算

ISO 8601 期間形式の INTERVAL値を使用して、TIMESTAMPTZ フィールドに対して算術演算を実行できます。これにより、データのフィルタリング時に、タイムスタンプから日、時間、分などの期間を加算または減算することができます。

たとえば、次のクエリは、タイムスタンプ(tsz )に0日を加算した値が2025-01-03T00:00:00+08:00と 等しくないエンティティをフィルタリングします:

expr = "tsz + INTERVAL 'P0D' != ISO '2025-01-03T00:00:00+08:00'"

results = client.query(
    collection_name, 
    filter=expr, 
    output_fields=["id", "tsz"], 
    limit=10
)

print("Query result: ", results)

# Expected output:
# Query result:  data: ["{'id': 1, 'tsz': '2024-12-31T16:00:00Z'}", "{'id': 2, 'tsz': '2025-01-01T16:00:00Z'}", "{'id': 4, 'tsz': '2025-01-03T16:00:00Z'}", "{'id': 5, 'tsz': '2025-01-04T16:00:00Z'}", "{'id': 6, 'tsz': '2025-01-05T16:00:00Z'}", "{'id': 7, 'tsz': '2025-01-06T16:00:00Z'}", "{'id': 8, 'tsz': '2025-01-07T16:00:00Z'}", "{'id': 9, 'tsz': '2025-01-08T16:00:00Z'}", "{'id': 10, 'tsz': '2025-01-09T16:00:00Z'}", "{'id': 11, 'tsz': '2025-01-10T16:00:00Z'}"]
// java
// nodejs
// go
# restful

INTERVAL 値はISO 8601期間表記に従います。例:

  • P1D → 1日

  • PT3H → 3時間

  • P2DT6H → 2日と6時間

INTERVAL の演算を、次のようなフィルター式で直接使用できます:

  • tsz + INTERVAL 'P3D' → 3日を加算

  • tsz - INTERVAL 'PT2H' → 2時間を差し引く

タイムスタンプによるフィルタリングでの検索

TIMESTAMPTZ によるフィルタリングとベクトル類似度検索を組み合わせることで、時間と類似度の両方の条件で検索結果を絞り込むことができます。

# Define a time-based filter expression
filter = "tsz > ISO '2025-01-05T00:00:00+08:00'"

res = client.search(
    collection_name=collection_name,             # Collection name
    data=[[0.1, 0.2, 0.3, 0.4]],                  # Query vector (must match collection's vector dim)
    limit=5,                                      # Max. number of results to return
    filter=filter,                                # Filter expression using TIMESTAMPTZ
    output_fields=["id", "tsz"],  # Fields to include in the search results
)

print("Search result: ", res)

# Expected output:
# Search result:  data: [[{'id': 10, 'distance': 0.9759000539779663, 'entity': {'tsz': '2025-01-09T16:00:00Z', 'id': 10}}, {'id': 9, 'distance': 0.9759000539779663, 'entity': {'tsz': '2025-01-08T16:00:00Z', 'id': 9}}, {'id': 8, 'distance': 0.9759000539779663, 'entity': {'tsz': '2025-01-07T16:00:00Z', 'id': 8}}, {'id': 7, 'distance': 0.9759000539779663, 'entity': {'tsz': '2025-01-06T16:00:00Z', 'id': 7}}, {'id': 6, 'distance': 0.9759000539779663, 'entity': {'tsz': '2025-01-05T16:00:00Z', 'id': 6}}]]
// java
// nodejs
// go
# restful

コレクションに2つ以上のベクトルフィールドがある場合、タイムスタンプフィルタリングを用いたハイブリッド検索を実行できます。詳細については、「マルチベクトルハイブリッド検索」を参照してください。

高度な使い方

高度な使用法として、さまざまなレベル(データベース、コレクション、クエリなど)でタイムゾーンを管理したり、インデックスを使用してTIMESTAMPTZ フィールドでのクエリを高速化したりできます。

さまざまなレベルでのタイムゾーンの管理

TIMESTAMPTZ フィールドのタイムゾーンは、データベースコレクション、またはクエリ/検索の各レベルで制御できます。

レベル

パラメータ

適用範囲

優先度

データベース

timezone

データベース内のすべてのコレクションに対するデフォルト値

最低

コレクション

timezone

そのコレクションのデータベースのデフォルトのタイムゾーン設定を上書きします

クエリ/検索/ハイブリッド検索

timezone

特定の1つの操作に対する一時的な上書き設定

最高

手順ごとの説明やコードサンプルについては、以下の専用ページを参照してください:

クエリの高速化

デフォルトでは、インデックスのないTIMESTAMPTZ フィールドに対するクエリは、すべての行を完全にスキャンするため、大規模なデータセットでは処理に時間がかかる場合があります。タイムスタンプクエリを高速化するには、TIMESTAMPTZ フィールドにSTL_SORT インデックスを作成してください。

詳細については、STL_SORTを参照してください。