空間データを最新の状態に保つことは、大規模に作業する際によくある課題であり、特に分析結果を継続的に運用システムに公開する必要がある場合に重要です。ArcGIS GeoAnalytics for Fabric を使用すると、分析出力を直接フィーチャ サービスに書き込むことができます。フィーチャ サービスを更新する際には、すべてを再書き込みしたくない場合があります。upsert オプションを使用すると、既存のフィーチャを更新し、新しいフィーチャを単一の効率的な操作で追加できます。この投稿では、upsert がフィーチャ サービスへの増分更新をどのように簡素化し、権威あるレイヤーを最新の状態に保ちながら安定したフィーチャ ID を維持し、下流のアプリやダッシュボードをサポートするかについて見ていきます。
このブログ投稿では、その仕組みを示すためにこのプロセスを順を追って説明します。デモンストレーションとして、新しいフィーチャ サービスを作成し、そのフィーチャ サービスからデータを読み込み、いくつかの行を更新し、その後 upsert を使って保存されたフィーチャ サービス内のその行だけを更新データで変更します。
フィーチャ サービスの作成
upsert の動作を示すために、まずフィーチャ サービスを作成します。簡単にするために、Esri の Living Atlas of the World からデータ レイヤーを読み込み、それを ArcGIS Online のアカウントに書き込みます。これが更新する「新しい」フィーチャ サービスになります。
まず、GeoAnalytics for Fabric ライブラリと Pyspark SQL 関数をインポートします。
# imports
import geoanalytics_fabric
import pyspark.sql.functions as F
次に、例として使用するために米国主要都市のデータセットを読み込みます。この場合、元の Living Atlas フィーチャ サービスからいくつかの属性だけを使用します。この例では、自動生成される OBJECTID フィールドを削除し、「My_ID」というフィールドで置き換えます。これは、新しいフィーチャ サービスを書き込む際に一意のインデックス付き OBJECTID を作成することを示すためだけに使います(そうしないと次のステップで書き込むときに OBJECTID フィールドが二重になります)。
# read in a dataset to use as an example for upsert
# US major cities dataset from ArcGIS Living Atlas of the World
myFS="https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/USA_Major_Cities_/FeatureServer/0"
myFSDataFrame = spark.read.format('feature-service').load(myFS)\
.select("OBJECTID", "NAME", "STATE_ABBR", "PLACE_FIPS", "SHAPE")\
.withColumn("My_ID", F.col("OBJECTID"))\
.drop("OBJECTID") # 元の OBJECTID フィールドは削除します。代わりに My_ID を upsert マッチング フィールドとして使用します。
display(myFSDataFrame)
得られた DataFrame をサンプル データセットとして使用し、それを書き込んで編集可能な新しいフィーチャ サービスとして ArcGIS Online アカウントに保存します。
そのためには、ArcGIS Online アカウントへの接続が必要です:
# データを書き込む gis を登録 - AGOL の資格情報を使用
geoanalytics_fabric.register_gis("myGIS", "https://arcgis.com", username="my_username", password="my_password")そして DataFrame を ArcGIS Online アカウントへ書き込みます。この初回書き込み時には upsertMatchingField を設定しています。これは upsert 時にマッチングに使うレイヤーフィールドを指定します。一意インデックスがある任意のフィールドが使え、この例では一意識別子である「My_ID」です。
新しいレイヤー作成時に upsertMatchingField を指定すると、その指定したフィールド(My_ID)に一意インデックスが作成されます。
# my gis に書き込み
# "My_ID" フィールドが upsert フィールドになるよう指定(一意インデックスが作成される)
myFSDataFrame.write.format('feature-service')\
.option("gis", "myGIS")\
.option("serviceName", "us_cities_upsert_example_with_unique_index")\
.option("layerName", "layer")\
.option("upsertMatchingField", "My_ID")\
.save()データの一部更新
このレイヤーからデータを再度取得して内容が期待通りか確認し、その後 upsert で更新するいくつかの行を特定します。ArcGIS Online アカウントへの接続オプションも指定しています。読み書きできるよう、ArcGIS Online アカウントが登録済みであることが重要です!
# 新しいフィーチャ サービスからデータ読み込み - この DataFrame で upsert 機能を実演
myNewFS = "https://your_service_URL"
myNewFSDataFrame = spark.read.format('feature-service')\
.option("gis", "myGIS")\
.load(myNewFS)
display(myNewFSDataFrame)

新しいフィーチャ サービスには元のすべてのフィールドと、新たに自動生成された OBJECTID フィールドがあります。
次に、一部のデータのみ更新したい場合どうなるか見てみましょう。簡単にするため最初の 2 つの ID のレコードだけ更新します。つまり、「Alabaster」を「New City 1」に、「Albertville」を「New City 2」に置き換えます:
# 2 行編集して更新
updated_row = myFSDataFrame.filter("My_ID in (1, 2)")\
.withColumn("NAME", F.when(F.col("My_ID") == 1, "New City Name 1").otherwise("New City Name 2"))
display(updated_row)
これら新しいレコードで ArcGIS Online 上のフィーチャ サービスを更新したい場合 - ただこの 2 行だけアップデートしたい場合は- upsert を使うことができます。この DataFrame の更新された 2 行だけを書き戻しましょう。書き戻す際はモードを「append」に設定し、upsertMatchingField に「My_ID」を指定します。これで該当レコードの一意 ID とマッチングして、その行だけ属性を書き換えます。
# 更新された行だけ upsert を使ってフィーチャ サービスへ書き戻す
service_url = "https://your_service_URL"
updated_row.write.mode("append").format('feature-service')\
.option("gis", "myGIS")\
.option("serviceURL", service_url)\
.option("upsertMatchingField", "My_ID")\
.option("layerName", "layer")\
.save()変更が反映されたか確認するため、再度フィーチャ サービスから読み込み内容を見てみましょう:
myfs_upsert_url = "https://your_service_URL"
myFSDataFrame_after_upsert = spark.read.format('feature-service')\
.option("gis", "myGIS")\
.load(myfs_upsert_url)
display(myFSDataFrame_after_upsert)

そして実際には更新が必要だった行はたった 2 行だけでした!これは通常、テーブル全体を書き換えるよりも効率的です。
まとめ
GeoAnalytics for Fabric を使って選択的に効率よくフィーチャ サービスを更新する方法について、有益なデモンストレーションになったことと思います!