Linked Data Entity Relationships
¶
このチュートリアルでは、NGSI-LD ユーザにバッチコマンドとエンティティのリレーションシップについて説明します。 このチュートリアルは、以前のスマート・ファームの例 で作成されたデータに基づいて構築され、一連の関連データ・エンティティを作成および関連付けて、 追加センサとファーム・ワーカをファームに作成します。
チュートリアルでは全体で cUrl コマンドを使用しますが、 Postman documentation としても利用できます。
エンティティとリレーションシップを理解¶
FIWARE プラットフォーム内では、エンティティのコンテキストは、実世界に存在する物理的または概念的なオブジェクトの 状態を表します。
ファーム管理情報システム (Farm Management Information System; FMIS) 内のエンティティ¶
NGSI-LD に基づく FMIS システム内のエンティティのリレーションシップを説明するために、一連のエンティティを作成する必要が あります。この簡略化された FMIS の場合、必要なエンティティは少数です。エンティティ間のリレーションシップは、 次のように定義されています:
- 納屋などの建物 (building) は、現実世界のレンガとモルタルの構造物です。Building エンティティには、
次のようなプロパティがあります:
- 建物の名前。例: "大きな赤い納屋"
- 建物のカテゴリ。例: "納屋"
- 住所 "Friedrichstraße 44, 10969 Kreuzberg, Berlin"
- 物理的な場所 (例: 52.5075 N, 13.3903 E)
- 充填レベル (filling level) - 建物が満杯である程度
- 温度 - 例: 21 °C
- 建物の所有者 (実在の人物) との関連 (association)
- TemperatureSensors や FillingLevelSensors などのスマート・デバイスは、一般的な Device データモデルを
拡張します。各 Device エンティティには、次のようなプロパティがあります:
- デバイスの説明
- デバイスのカテゴリ (例: sensor, actuator, both)
- デバイスが測定しているプロパティの名前 (例: temperature)
- デバイスが測定している資産 (asset) (例: building)との関連 (association)
- person は、農家や農業労働者を代表するエンティティです。各 Person エンティティには、次のようなプロパティが
あります:
- その人の名前。例: "Mr. Jones"
- 役職
- 彼らが所有する農場の建物との関連 (association)
- 私たちが農場でやっていることのタスク。これは概念的なエンティティであり、労働者、農産物、場所を関連付けるために
使用されます。Task エンティティには次のようなプロパティがあります。
- タスクの名前 (例: Spray Fertilizer XXX on field Y)
- タスクのステータス (例: scheduled, in progress, completed)
- タスクを実行するワーカー (つまり、Person エンティティ) への関連付け
- 使用する製品 (例: 肥料 Fertilizer エンティティ) への関連付け
- 使用する場所 (例: PartField エンティティなど) への関連付け
ご覧のとおり、上記で定義された各エンティティには、静的データと動的データが混在しています。一部のプロパティは変更される
可能性があります。魚の加水分解物などの有機肥料 Fertilizer は、その formula
(配合) を変更したり、
干し草を販売したり、納屋の fillingLevel
(充填レベル) を減らしたりすることができます。
注 このチュートリアルでは、次のタイポグラフィ・スタイルを使用しています :
- エンティティ・タイプは、bold text (太字) になっています
- データ属性は
monospace text
(モノスペース・テキスト) で書かれています- 実世界のアイテムはプレーン・テキストを使用します
したがって、実世界の人物は、コンテキスト・データでは Person エンティティによって表され、人物が所有する実世界の 納屋 (barn) は、
owner
属性を持つ Building エンティティによってコンテキスト・データで表されます。
アーキテクチャ¶
デモ FMIS アプリケーションは、Context Broker に準拠した NGSI-LD 呼び出しを送受信します。標準化された NGSI-LD インターフェースは複数の Context Broker で利用できるため、1つだけ選択する必要があります。たとえば、 Orion Context Broker です。 したがって、アプリケーションは1つの FIWARE コンポーネントのみを使用します。
現在、Orion Context Broker は、保持しているコンテキスト・データの永続性を維持するためにオープンソースの MongoDB テクノロジに依存しています。
データ交換の相互運用性を促進するために、NGSI-LD context brokers は
JSON-LD @context
ファイルを明示的に公開して、コンテキスト・
エンティティ内に保持されるデータを定義します。これにより、すべてのエンティティ・タイプとすべての属性に一意の URI
が定義され、NGSI ドメイン外の他のサービスがデータ構造の名前を選択できるようになります。すべての @context ファイル
がネットワーク上で利用可能である必要があります。このチュートリアルでは、チュートリアル・アプリケーションを使用して、
一連の静的ファイルをホストします。
したがって、アーキテクチャは次の3つの要素で構成されます:
- Orion Context Broker は、 NGSI-LD を使用してリクエストを受信します
- 基礎となる MongoDB データベース:
- データ・エンティティ、サブスクリプション、レジストレーションなどのコンテキスト・データ情報を保持するために Orion Context Broker によって使用されます
- チュートリアル・アプリケーションは次のことを行います:
2つの要素間のすべての対話は HTTP リクエストによって開始されるため、要素をコンテナ化して、公開されたポートから 実行できます。
必要な構成情報は、関連する docker-compose.yml
ファイルの services セクションにあります。
以前のチュートリアルで説明しています。
前提条件¶
Docker と Docker Compose¶
シンプルにするために、すべてのコンポーネントは Docker を使用して実行されます。 Docker は、それぞれの環境に分離されたさまざまなコンポーネントを可能にするコンテナ・テクノロジです。
- Windows に Docker をインストールするには、こちらの指示に従ってください
- Mac に Docker をインストールするには、こちらの指示に従ってください
- Linux に Docker をインストールするには、こちらの手順に従ってください
Docker Compose は、マルチコンテナ Docker アプリケーションを定義して実行するためのツールです。 YAMLファイル を使用して、アプリケーションに必要なサービスを設定します。これは、すべてのコンテナ・サービスを単一のコマンドで起動 できることを意味します。Docker Compose は、Docker for Windows および Docker for Mac の一部としてデフォルトでインストール されますが、Linux ユーザはこちらにある手順に従う必要があります。
次のコマンドを使用して、現在の Docker および DockerCompose のバージョンを確認できます:
docker-compose -v
docker version
Docker version 20.10 以降および Docker Compose 1.29 以降を使用していることを確認し、 必要に応じてアップグレードしてください。
Cygwin for Windows¶
簡単な bash スクリプトを使ってサービスを開始します。Windows ユーザは、Windows 上の Linux ディストリビューションに 似たコマンドライン機能を提供するために cygwin をダウンロードするべきです。
起動¶
すべてのサービスは、リポジトリ内で提供される services Bash スクリプトを実行して、 コマンドラインから初期化できます。以下のようにコマンドを実行して、リポジトリのクローンを作成して必要なイメージを 作成してください :
git clone https://github.com/FIWARE/tutorials.Entity-Relationships.git
cd tutorials.Entity-Relationships
git checkout NGSI-LD
./services start
このコマンドは、起動時にシード・データ (Building, Person, TemperatureSensor, FillingLevelSensor, Herbicide, PartField) をインポートします。
注: クリーンアップして最初からやり直す場合は、次のコマンドで実行できます:
./services stop
データ・エンティティの作成と関連付け¶
一度に複数のエンティティを作成¶
以前のチュートリアルでは、各エンティティを個別に作成しました。
同時に複数のセンサを作成しましょう。このリクエストは、コンビニエンス・バッチ処理エンドポイントを使用して5つの
エンティティを作成します。バッチ処理では /ngsi-ld/v1/entityOperations/
エンドポイントが使用されます。
upsert
エンドポイントは、エンティティ存在しない場合は新しいエンティティを作成し、存在する場合は既存の
エンティティを上書きすることを意味します。
さまざまなデバイスを区別するために、各温度センサには type=TemperatureSensor
が割り当てられています。category
などの実際のプロパティは、各デバイスにプロパティとして追加されています。
1 リクエスト:¶
curl -X POST 'http://localhost:1026/ngsi-ld/v1/entityOperations/upsert' \
-H 'Content-Type: application/json' \
-H 'Link: <'http://context/ngsi-context.jsonld'>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-H 'Accept: application/ld+json' \
--data-raw '[
{
"id": "urn:ngsi-ld:TemperatureSensor:001",
"type": "TemperatureSensor",
"description" : {"type": "Property", "value": "Temperature Gauge 1"},
"category": {"type": "Property", "value": "sensor"},
"controlledProperty" : {"type": "Property", "value": "temperature"},
"temperature": {"type": "Property", "value": 20, "unitCode": "CEL"}
},
{
"id": "urn:ngsi-ld:TemperatureSensor:002",
"type": "TemperatureSensor",
"description" : {"type": "Property", "value": "Temperature Gauge 2"},
"category": {"type": "Property", "value": "sensor"},
"controlledProperty" : {"type": "Property", "value": "temperature"},
"temperature": {"type": "Property", "value": 21, "unitCode": "CEL"}
},
{
"id": "urn:ngsi-ld:TemperatureSensor:003",
"type": "TemperatureSensor",
"description" : {"type": "Property", "value": "Temperature Gauge 3"},
"category": {"type": "Property", "value": "sensor"},
"controlledProperty" : {"type": "Property", "value": "temperature"},
"temperature": {"type": "Property", "value": 27, "unitCode": "CEL"}
}
]'
同様に、type=FillingLevelSensor
を使用して一連の FillingLevelSensors エンティティを作成できます。
2 リクエスト:¶
curl -X POST 'http://localhost:1026/ngsi-ld/v1/entityOperations/upsert' \
-H 'Content-Type: application/json' \
-H 'Link: <'http://context/ngsi-context.jsonld'>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-H 'Accept: application/ld+json' \
--data-raw '[
{
"id": "urn:ngsi-ld:FillingLevelSensor:001",
"type": "FillingLevelSensor",
"description" : {"type": "Property", "value": "Filling Level Sensor 1"},
"category": {"type": "Property", "value": "sensor"},
"controlledProperty" : {"type": "Property", "value": "fillingLevel"},
"fillingLevel": {"type": "Property", "value": 1, "unitCode": "C62"}
},
{
"id": "urn:ngsi-ld:FillingLevelSensor:002",
"type": "FillingLevelSensor",
"description" : {"type": "Property", "value": "Filling Level Sensor 2"},
"category": {"type": "Property", "value": "sensor"},
"controlledProperty" : {"type": "Property", "value": "fillingLevel"},
"fillingLevel": {"type": "Property", "value": 0.9, "unitCode": "C62"}
},
{
"id": "urn:ngsi-ld:FillingLevelSensor:003",
"type": "FillingLevelSensor",
"description" : {"type": "Property", "value": "Filling Gauge 3"},
"category": {"type": "Property", "value": "sensor"},
"controlledProperty" : {"type": "Property", "value": "fillingLevel"},
"fillingLevel": {"type": "Property", "value": 0.8, "unitCode": "C62"}
}
]'
どちらの場合も、NGSI-LD 仕様
に従って各エンティティ id
をエンコードしました - プロポーザルは、各 id
が標準形式に従う URN であるというものです:
urn:ngsi-ld:<entity-type>:<entity-id>
。 これは、システム内のすべての id
が一意になることを意味します。
デバイス情報は、/ngsi-ld/v1/entities
エンドポイントで GET リクエストを行うことでリクエストできます。たとえば、
デバイスのコンテキスト・データを返すためです。
3 リクエスト:¶
curl -X GET 'http://localhost:1026/ngsi-ld/v1/entities/?type=TemperatureSensor,FillingLevelSensor&options=keyValues' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"'
レスポンス:¶
[
{
"@context": "http://context/ngsi-context.jsonld",
"id": "urn:ngsi-ld:TemperatureSensor:001",
"type": "TemperatureSensor",
"description": "Temperature Gauge 1",
"category": "sensor",
"controlledProperty": "temperature",
"temperature": 20
},
{
"@context": "http://context/ngsi-context.jsonld",
"id": "urn:ngsi-ld:TemperatureSensor:002",
"type": "TemperatureSensor",
"description": "Temperature Gauge 2",
"category": "sensor",
"controlledProperty": "temperature",
"temperature": 21
},
... etc
]
ご覧のように、現在、description
, category
, controledProperty
の3つの追加プロパティ属性があります。
1対1または1対多のリレーションシップの作成¶
データベースでは、外部キー (foreign keys) は1対1または1対多のリレーションシップ (one-to-one or one-to-many relationship)
を指定するためによく使用されます。たとえば、1つの建物に多数のデバイスを収容できます。この情報を記憶するには、
外部キーと同様の関連付けリレーションシップ (association relationship) を追加する必要があります。バッチ処理を再度使用して、
既存の TemperatureSensor エンティティと FillingLevelSensor エンティティを修正し、デバイスによって制御される
各建物との1対1のリレーションシップを保持する controlledAsset
属性を追加できます。Smart Data Model によると、
Device
定義 https://uri.fiware.org/ns/data-models#controlledAsset
はこのリレーションシップに使用される URI の長い名前であり、
controlledAsset
属性の値は Building エンティティ自体に関連付けられた URN に対応します。
URN は、標準形式に従います: urn:ngsi-ld:<entity-type>:<entity-id>
4 リクエスト:¶
次のリクエストは、6つのデバイスを urn:ngsi-ld:Building:farm001
, urn:ngsi-ld:Building:barn002
および
urn:ngsi-ld:Building:farm002
に6つのデバイスを関連付けます。
curl -G -iX POST 'http://localhost:1026/ngsi-ld/v1/entityOperations/upsert' \
-d 'options=update' \
-H 'Content-Type: application/json' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
--data-raw '[
{
"id": "urn:ngsi-ld:TemperatureSensor:001",
"type": "TemperatureSensor",
"controlledAsset": {"type": "Relationship", "object": "urn:ngsi-ld:Building:farm001"}
},
{
"id": "urn:ngsi-ld:TemperatureSensor:002",
"type": "TemperatureSensor",
"controlledAsset": {"type": "Relationship", "object": "urn:ngsi-ld:Building:barn002"}
},
{
"id": "urn:ngsi-ld:FillingLevelSensor:003",
"type": "FillingLevelSensor",
"controlledAsset": {"type": "Relationship", "object": "urn:ngsi-ld:Building:farm002"}
},
{
"id": "urn:ngsi-ld:FillingLevelSensor:001",
"type": "FillingLevelSensor",
"controlledAsset": {"type": "Relationship", "object": "urn:ngsi-ld:Building:farm001"}
},
{
"id": "urn:ngsi-ld:FillingLevelSensor:002",
"type": "FillingLevelSensor",
"controlledAsset": {"type": "Relationship", "object": "urn:ngsi-ld:Building:barn002"}
},
{
"id": "urn:ngsi-ld:TemperatureSensor:003",
"type": "TemperatureSensor",
"controlledAsset": {"type": "Relationship", "object": "urn:ngsi-ld:Building:farm002"}
}
]'
これで、デバイス情報が再度リクエストされると、レスポンスが変更され、前の手順で追加された新しいプロパティ
controlledAsset
が含まれます。
5 リクエスト:¶
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:TemperatureSensor001' \
-d 'options=keyValues' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"'
レスポンス:¶
controlledAsset
属性を含む更新されたレスポンスを以下に示します:
{
"@context": "http://context/ngsi-context.jsonld",
"id": "urn:ngsi-ld:TemperatureSensor:001",
"type": "TemperatureSensor",
"description": "Temperature Gauge 1",
"category": "sensor",
"controlledProperty": "temperature",
"temperature": 20,
"controlledAsset": "urn:ngsi-ld:Building:farm001"
}
外部キー・リレーションシップ (Foreign Key Relationship) の読み取り¶
子エンティティから親エンティティへの読み取り¶
options=keyValues
設定を使用して、既知の Device エンティティから属性リレーションシップ情報を取得するように
リクエストすることもできます。
6 リクエスト:¶
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:TemperatureSensor:001' \
-d 'options=keyValues' \
-d 'attrs=controlledAsset' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-H 'Accept: application/json'
レスポンス:¶
{
"id": "urn:ngsi-ld:TemperatureSensor:001",
"type": "TemperatureSensor",
"controlledAsset": "urn:ngsi-ld:Building:farm001"
}
これは、"id=urn:ngsi-ld:Building:farm001
を使用して Building エンティティ内でセンサの読み取りを行っている"
と解釈できます。
親エンティティから子エンティティへの読み取り¶
親から子への読み取りは、次のクエリを使用して実行できます:
7 リクエスト:¶
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/entities' \
-d 'q=controlledAsset==%22urn:ngsi-ld:Building:farm001%22' \
-d 'attrs=controlledAsset' \
-d 'options=keyValues' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"'
このリクエストは、URN urn:ngsi-ld:Building:farm001
に関連付けられている、すべての Device エンティティの id
を
要求しています。レスポンスは、次に示されているように JSON 配列です。
レスポンス:¶
[
{
"@context": "http://context/ngsi-context.jsonld",
"id": "urn:ngsi-ld:TemperatureSensor:001",
"type": "TemperatureSensor",
},
{
"@context": "http://context/ngsi-context.jsonld",
"id": "urn:ngsi-ld:FillingLevelSensor:001",
"type": "FillingLevelSensor",
}
]
平易な英語では、これは "urn:ngsi-ld:Building:farm001
に2つのデバイスがあります" と解釈できます。
リクエストは、count=true
を使用して変更でき、基準を満たすエンティティの数を返します。
8 リクエスト:¶
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/entities' \
-d 'q=controlledAsset==%22urn:ngsi-ld:Building:farm001%22' \
-d 'attrs=controlledAsset' \
-d 'options=keyValues' \
-d 'count=true' \
-d 'limit=0' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"'
影響を受けるエンティティの数を示す HTTP ヘッダをレスポンスの一部として返します:
レスポンス:¶
NGSILD-Results-Count: 2
多対多のリレーションシップの作成¶
ブリッジ・テーブルは、多対多のリレーションシップ (many-to-many relationships) を関連付けるためによく使用されます。 たとえば、FMIS 内のすべてのスプレー作業では、農場労働者、適用する製品、および処理を適用する場所 (PartField と呼ばれる) を関連付ける必要があります。
"除草剤 (herbicide) をフィールドにスプレーするように作業者に指示する" というコンテキスト情報を保持するには、他のエンティティ
からのデータを関連付けるために存在する新しいデータ・エンティティ Task を作成する必要があります。Person, Herbicide
および PartField エンティティとの外部キー・リレーションシップがあるため、field
, herbicide
および worker
と呼ばれるリレーションシップ属性が必要です。
タスクの割り当ては、リレーションシップ情報とその他の追加プロパティ (description
および status
など) を保持する
エンティティを作成するだけで実行できます。
9 リクエスト:¶
curl -L -X POST 'http://localhost:1026/ngsi-ld/v1/entities/' \
-H 'Content-Type: application/json' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
--data-raw '{
"id": "urn:ngsi-ld:Task:001",
"type": "Task",
"worker": {"type": "Relationship", "object": "urn:ngsi-ld:Person:001"},
"field": {"type": "Relationship", "object": "urn:ngsi-ld:PartField:002"},
"product": {"type": "Relationship", "object": "urn:ngsi-ld:Herbicide:001"},
"description": {"type": "Property", "value": "Spray the North Field with Agent Orange"},
"status": {"type": "Property", "value": "scheduled"},
"dueDate": {"type": "Property", "value": "2021-07-16"}
}'
ブリッジ・テーブルからの読み取り¶
ブリッジ・テーブル・エンティティから読み取るときは、エンティティの type
がわかっている必要があります。
少なくとも1つの Task エンティティを作成した後、次のリクエストを行うことによって、
"フィールド urn:ngsi-ld:PartField:002
でアクティビティが割り当てられているワーカーはどれですか?"
というクエリを実行できます。
19 リクエスト:¶
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/entities' \
-d 'q=field==%22urn:ngsi-ld:PartField:002%22' \
-d 'options=keyValues' \
-d 'attrs=worker' \
-d 'type=Task' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-H 'Accept: application/json'
レスポンス:¶
[
{
"id": "urn:ngsi-ld:Task:001",
"type": "Task",
"worker": "urn:ngsi-ld:Person:001"
}
]
同様に、次に示されているようにリクエストを変更することによって、"どのフィールドが urn:ngsi-ld:Herbicide:001
を使用して処理されるか?” をリクエストできます。
11 リクエスト:¶
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/entities' \
-d 'q=product==%22urn:ngsi-ld:Herbicide:001%22' \
-d 'options=keyValues' \
-d 'attrs=field' \
-d 'type=Task' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-H 'Accept: application/json'
レスポンス:¶
[
{
"id": "urn:ngsi-ld:Task:001",
"type": "Task",
"field": "urn:ngsi-ld:PartField:002"
}
]
プロパティのリレーションシップ¶
Properties-of-Properties および Relationships of Properties はメタデータです。これらのようなメタデータ・ エンティティをコンテキスト・データに追加すると、ユーザはエンティティのリレーションシップのグラフをナビゲートし、 システムの状態についてさらに洞察を得ることができます。
納屋の温度を取得¶
温度センサからの温度測定値については、すでに説明しました。このデータを別のエンティティに複製する必要がある場合も
あります。たとえば、納屋 (barn) のセンサの温度測定値は、納屋自体の温度測定値でもあります。ダミーの読み取り値は
すでに urn:ngsi-ld:Building:farm001
エンティティに追加されており、GET リクエストで取得できます:
12 リクエスト:¶
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:Building:farm001' \
-d 'attrs=temperature' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-H 'Accept: application/json'
レスポンス:¶
{
"id": "urn:ngsi-ld:Building:farm001",
"type": "Building",
"temperature": {
"type": "Property",
"value": 20,
"unitCode": "CEL",
"providedBy": {
"type": "Relationship",
"object": "urn:ngsi-ld:TemperatureSensor:001"
}
}
}
ご覧のように、temperature
プロパティは、測定のプロバイダに関する追加情報を保持します。これにより、追加の推論を
行うことができます。
次のステップ¶
高度な機能を追加することで、アプリケーションに複雑さを加える方法を知りたいですか? このシリーズの 他のチュートリアルを読むことで見つけることができます
License¶
MIT © 2020 FIWARE Foundation e.V.