メインコンテンツまでスキップ

ジオメトリフィールド

地理情報システム(GIS)、マッピングツール、位置情報サービスなどのアプリケーションを構築する場合、幾何学データを格納し、クエリを実行する必要がよくあります。Milvus の GEOMETRY データ型は、柔軟な幾何学データをネイティブに格納およびクエリする方法を提供することで、この課題を解決します。

ベクトルの類似性と空間制約を組み合わせる必要がある場合は、GEOMETRY フィールドを使用します。たとえば、次のような場合です。

  • 位置情報サービス(LBS):「この街区の範囲内で類似する POI を検索する」

  • マルチモーダル検索:「この地点から 1km 以内にある類似写真を取得する」

  • 地図と物流:「リージョン内のアセット」または「パスと交差するルート」

Notes

GEOMETRY フィールドを使用するには、SDK を最新バージョンにアップグレードしてください。

GEOMETRY フィールドとは?​

GEOMETRY フィールドは、Zilliz Cloud のスキーマで定義されるデータ型(DataType.GEOMETRY)で、幾何学データを格納します。ジオメトリフィールドを扱う場合、データの挿入とクエリの両方に使用される人間が読める形式である Well-Known Text(WKT) 形式を使用してデータを操作します。内部では、Zilliz Cloud が効率的な格納と処理のために WKT を Well-Known Binary(WKB) に変換しますが、WKB を直接扱う必要はありません。

GEOMETRY データ型は、次の幾何学オブジェクトをサポートします。

  • POINT: POINT (x y)。たとえば、POINT (13.403683 52.520711) で、x は経度、y は緯度です。

  • LINESTRING: LINESTRING (x1 y1, x2 y2, …)。たとえば、LINESTRING (13.40 52.52, 13.41 52.51) です。

  • POLYGON: POLYGON ((x1 y1, x2 y2, x3 y3, x1 y1))。たとえば、POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10)) です。

  • MULTIPOINT: MULTIPOINT ((x1 y1), (x2 y2), …)。たとえば、MULTIPOINT ((10 40), (40 30), (20 20), (30 10)) です。

  • MULTILINESTRING: MULTILINESTRING ((x1 y1, …), (xk yk, …))。たとえば、MULTILINESTRING ((10 10, 20 20, 10 40), (40 40, 30 30, 40 20, 30 10)) です。

  • MULTIPOLYGON: MULTIPOLYGON (((outer ring ...)), ((outer ring ...)))。たとえば、MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5))) です。

  • GEOMETRYCOLLECTION: GEOMETRYCOLLECTION(POINT(x y), LINESTRING(x1 y1, x2 y2), ...)。たとえば、GEOMETRYCOLLECTION (POINT (40 10), LINESTRING (10 10, 20 20, 10 40), POLYGON ((40 40, 20 45, 45 30, 40 40))) です。

基本操作​

GEOMETRY フィールドを使用するワークフローでは、コレクションスキーマでフィールドを定義し、幾何学データを挿入してから、特定のフィルター式を使用してデータをクエリします。

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

GEOMETRY フィールドを使用するには、コレクションを作成するときにコレクションスキーマで明示的に定義します。次の例では、DataType.GEOMETRY 型の geo フィールドを持つコレクションを作成する方法を示します。

python
from pymilvus import MilvusClient, DataType

dim = 8
collection_name = "geo_collection"
client = MilvusClient("YOUR_CLUSTER_ENDPOINT")

# Create schema with a GEOMETRY field
schema = client.create_schema(enable_dynamic_field=True)
schema.add_field("id", DataType.INT64, is_primary=True)
schema.add_field("embeddings", DataType.FLOAT_VECTOR, dim=dim)
schema.add_field("geo", DataType.GEOMETRY, nullable=True)
schema.add_field("name", DataType.VARCHAR, max_length=128)

client.create_collection(collection_name, schema=schema, consistency_level="Strong")
Notes

この例では、コレクションスキーマで定義された GEOMETRY フィールドは、nullable=True により null 値を許可します。詳細は、Nullable & Default を参照してください。

ステップ 2: データを挿入する​

WKT 形式で幾何学データを含むエンティティを挿入します。次に、複数の地理ポイントを含む例を示します。

python
geo_points = [
'POINT(13.399710 52.518010)',
'POINT(13.403934 52.522877)',
'POINT(13.405088 52.521124)',
'POINT(13.408223 52.516876)',
'POINT(13.400092 52.521507)',
'POINT(13.408529 52.519274)',
]

rows = [
{"id": 1, "name": "Shop A", "embeddings": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8], "geo": geo_points[0]},
{"id": 2, "name": "Shop B", "embeddings": [0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9], "geo": geo_points[1]},
{"id": 3, "name": "Shop C", "embeddings": [0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0], "geo": geo_points[2]},
{"id": 4, "name": "Shop D", "embeddings": [0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 0.1], "geo": geo_points[3]},
{"id": 5, "name": "Shop E", "embeddings": [0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 0.1, 0.2], "geo": geo_points[4]},
{"id": 6, "name": "Shop F", "embeddings": [0.6, 0.7, 0.8, 0.9, 1.0, 0.1, 0.2, 0.3], "geo": geo_points[5]},
]

insert_result = client.insert(collection_name, rows)
print(insert_result)

# Expected output:
# {'insert_count': 6, 'ids': [1, 2, 3, 4, 5, 6]}

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

GEOMETRY フィールドでフィルタリング操作を実行する前に、次の点を確認してください。

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

  • コレクションがメモリにロードされていること。

コードを表示
python
index_params = client.prepare_index_params()
index_params.add_index(field_name="embeddings", metric_type="L2")

client.create_index(collection_name, index_params)
client.load_collection(collection_name)

これらの要件を満たしたら、専用のジオメトリ演算子を含む式を使用して、幾何学値に基づいてコレクションをフィルターできます。

フィルター式を定義する​

GEOMETRY フィールドをフィルターするには、式でジオメトリ演算子を使用します。

  • 一般: {operator}(geo_field, '{wkt}')

  • 距離ベース: ST_DWITHIN(geo_field, '{wkt}', distance)

各要素の意味は次のとおりです。

  • operator は、サポートされているジオメトリ演算子の 1 つです(例: ST_CONTAINS、ST_INTERSECTS)。演算子名は、すべて大文字またはすべて小文字で指定する必要があります。サポートされている演算子の一覧については、Supported geometry operators を参照してください。

  • geo_field は、GEOMETRY フィールドの名前です。

  • '{wkt}' は、クエリ対象のジオメトリの WKT 表現です。

  • distance は、ST_DWITHIN 専用のしきい値です。

次の例では、フィルター式でさまざまなジオメトリ固有の演算子を使用する方法を示します。

例 1: 矩形領域内のエンティティを検索する​

python
top_left_lon, top_left_lat = 13.403683, 52.520711
bottom_right_lon, bottom_right_lat = 13.455868, 52.495862
bounding_box_wkt = f"POLYGON(({top_left_lon} {top_left_lat}, {bottom_right_lon} {top_left_lat}, {bottom_right_lon} {bottom_right_lat}, {top_left_lon} {bottom_right_lat}, {top_left_lon} {top_left_lat}))"

query_results = client.query(
collection_name,
filter=f"st_within(geo, '{bounding_box_wkt}')",
output_fields=["name", "geo"]
)
for ret in query_results:
print(ret)

# Expected output:
# {'name': 'Shop D', 'geo': 'POINT (13.408223 52.516876)', 'id': 4}
# {'name': 'Shop F', 'geo': 'POINT (13.408529 52.519274)', 'id': 6}

例 2: 中心点から 1km 以内のエンティティを検索する​

python
center_point_lon, center_point_lat = 13.403683, 52.520711
radius_meters = 1000.0
central_point_wkt = f"POINT({center_point_lon} {center_point_lat})"

query_results = client.query(
collection_name,
filter=f"st_dwithin(geo, '{central_point_wkt}', {radius_meters})",
output_fields=["name", "geo"]
)
for ret in query_results:
print(ret)

# Expected output:
# {'name': 'Shop A', 'geo': 'POINT (13.39971 52.51801)', 'id': 1}
# {'name': 'Shop B', 'geo': 'POINT (13.403934 52.522877)', 'id': 2}
# {'name': 'Shop C', 'geo': 'POINT (13.405088 52.521124)', 'id': 3}
# {'name': 'Shop D', 'geo': 'POINT (13.408223 52.516876)', 'id': 4}
# {'name': 'Shop E', 'geo': 'POINT (13.400092 52.521507)', 'id': 5}
# {'name': 'Shop F', 'geo': 'POINT (13.408529 52.519274)', 'id': 6}

例 3: ベクトルの類似性と空間フィルターを組み合わせる​

python
vectors_to_search = [[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]]
result = client.search(
collection_name,
vectors_to_search,
limit=3,
output_fields=["name", "geo"],
filter=f"st_within(geo, '{bounding_box_wkt}')"
)
for hits in result:
for hit in hits:
print(f"hit: {hit}")

# Expected output:
# hit: {'id': 4, 'distance': 1.1200000047683716, 'entity': {'geo': 'POINT (13.408223 52.516876)', 'name': 'Shop D'}}
# hit: {'id': 6, 'distance': 2.0, 'entity': {'geo': 'POINT (13.408529 52.519274)', 'name': 'Shop F'}}

次のステップ: クエリを高速化する​

デフォルトでは、インデックスのない GEOMETRY フィールドに対するクエリはすべての行のフルスキャンを実行するため、大規模なデータセットでは遅くなる可能性があります。幾何学クエリを高速化するには、GEOMETRY フィールドに AUTOINDEX インデックスを作成します。

詳細は、RTREE を参照してください。

よくある質問​

コレクションで動的フィールド機能を有効にした場合、幾何学データを動的フィールドのキーに挿入できますか?​

いいえ、幾何学データを動的フィールドに挿入することはできません。幾何学データを挿入する前に、コレクションスキーマで GEOMETRY フィールドが明示的に定義されていることを確認してください。

GEOMETRY フィールドは mmap 機能をサポートしていますか?​

はい、GEOMETRY フィールドは mmap をサポートしています。詳細は、Use mmap を参照してください。

GEOMETRY フィールドを nullable に設定したり、デフォルト値を設定したりできますか?​

はい、GEOMETRY フィールドは nullable 属性と WKT 形式のデフォルト値をサポートしています。詳細は、Nullable & Default を参照してください。