Attribute Metadata
Apart from metadata elements to which Orion pays special attention (e.g. ID, etc.), users can attach their own metadata to entity attributes. These metadata elements are processed by Orion in a transparent way: Orion simply stores them in the database at update time and retrieves them at query and notification time.
You can use any name for your custom metadata except for a few reserved names, used for special metadata that are interpreted by Orion:
- ID
- location, which is currently deprecated, but still supported
- The ones defined in "System/builtin in metadata" section in the NGSIv2 spec
Its management is slightly different in NGSIv1 and NGSIv2, so it is described in different sections.
Custom attribute metadata (using NGSIv2)
For example, to create an entity Room1 with attribute "temperature", and associate metadata "accuracy" to "temperature":
curl localhost:1026/v2/entities -s -S --header 'Content-Type: application/json' \
-d @- <<EOF
{
"id": "Room1",
"type": "Room",
"temperature": {
"value": 26.5,
"type": "Float",
"metadata": {
"accuracy": {
"value": 0.8,
"type": "Float"
}
}
}
}
EOF
Unlike NGSIv1, at the moment NGSIv2 doesn't define an operation
to update metadata regardless of the attribute value being updated
or not. In addition, it doesn't define an operation to add metadata after
attribute creation. In other words, the whole metadata array is updated
along with attribute value and type in the PUT /v2/entities/{id}/attrs/{attrName}
operation.
We can check that temperature includes the metadata:
curl localhost:1026/v2/entities/Room1 -s -S \
--header 'Accept: application/json' | python -mjson.tool
which response is
{
"id": "Room1",
"temperature": {
"metadata": {
"accuracy": {
"type": "Float",
"value": 0.8
}
},
"type": "Float",
"value": 26.5
},
"type": "Room"
}
At the moment, NGSIv2 doesn't allow to delete individual metadata elements once introduced.
However, you can delete all metadata updating the attribute with metadata
set to {}
.
Note that, from the point of view of subscriptions, changing the metadata of a given attribute is considered a change even though the attribute value itself hasn't changed.
Custom attribute metadata (using NGSIv1)
For example, to create an entity Room1 with attribute "temperature", and associate metadata "accuracy" to "temperature":
(curl localhost:1026/v1/updateContext -s -S --header 'Content-Type: application/json' \
--header 'Accept: application/json' -d @- | python -mjson.tool) <<EOF
{
"contextElements": [
{
"type": "Room",
"isPattern": "false",
"id": "Room1",
"attributes": [
{
"name": "temperature",
"type": "float",
"value": "26.5",
"metadatas": [
{
"name": "accuracy",
"type": "float",
"value": "0.8"
}
]
}
]
}
],
"updateAction": "APPEND"
}
EOF
Metadata can be updated regardless of the attribute value being updated or not. For example, next updateContext shows how "accuracy" is updated to 0.9 although the value of the temperature iself is still 26.5:
(curl localhost:1026/v1/updateContext -s -S --header 'Content-Type: application/json' \
--header 'Accept: application/json' -d @- | python -mjson.tool) <<EOF
{
"contextElements": [
{
"type": "Room",
"isPattern": "false",
"id": "Room1",
"attributes": [
{
"name": "temperature",
"type": "float",
"value": "26.5",
"metadatas": [
{
"name": "accuracy",
"type": "float",
"value": "0.9"
}
]
}
]
}
],
"updateAction": "UPDATE"
}
EOF
Metadata can be added after attribute creation. For example, if we want to add metadata "average" to "temperature" (in addition to the existing "precision"):
(curl localhost:1026/v1/updateContext -s -S --header 'Content-Type: application/json' \
--header 'Accept: application/json' -d @- | python -mjson.tool) <<EOF
{
"contextElements": [
{
"type": "Room",
"isPattern": "false",
"id": "Room1",
"attributes": [
{
"name": "temperature",
"type": "float",
"value": "26.5",
"metadatas": [
{
"name": "average",
"type": "float",
"value": "22.4"
}
]
}
]
}
],
"updateAction": "UPDATE"
}
EOF
We can check that temperature includes both attributes
(curl localhost:1026/v1/contextEntities/Room1 -s -S \
--header 'Accept: application/json' | python -mjson.tool) <<EOF
{
"contextElements": [
{
"type": "Room",
"isPattern": "false",
"id": "Room1",
"attributes": [
{
"name": "temperature",
"type": "float",
"value": "26.5",
"metadatas": [
{
"name": "average",
"type": "float",
"value": "22.4"
},
{
"name": "accuracy",
"type": "float",
"value": "0.9"
}
]
}
]
}
],
"statusCode": {
"code": "200",
"reasonPhrase": "OK"
}
}
Note that, from the point of view of subscriptions, changing the metadata of a given attribute or adding a new metadata element is considered a change even if attribute value itself hasn't changed. Metadata elements cannot be deleted once introduced: in order to delete metadata elements you have to remove the entity attribute (see DELETE action type), then re-create it (see APPEND action type).
Metadata ID for attributes
This functionality is not included in the NGSIv2 API.
Sometimes, you could want to model attributes belonging to an entity which share the same name and type. For example, let's consider an entity "Room1" which has two temperature sensors: one in the ground and other in the wall. We can model this as two instances of the attribute "temperature", one with ID "ground" and the other with the ID "wall". We use the metadata ID for this purpose. Let's illustrate with an example.
First, we create the Room1 entity:
(curl localhost:1026/v1/updateContext -s -S --header 'Content-Type: application/json' \
--header 'Accept: application/json' -d @- | python -mjson.tool) <<EOF
{
"contextElements": [
{
"type": "Room",
"isPattern": "false",
"id": "Room1",
"attributes": [
{
"name": "temperature",
"type": "float",
"value": "23.5",
"metadatas": [
{
"name": "ID",
"type": "string",
"value": "ground"
}
]
},
{
"name": "temperature",
"type": "float",
"value": "23.8",
"metadatas": [
{
"name": "ID",
"type": "string",
"value": "wall"
}
]
}
]
}
],
"updateAction": "APPEND"
}
EOF
Now, we can query for temperature to get both instances:
(curl localhost:1026/v1/queryContext -s -S --header 'Content-Type: application/json' \
--header 'Accept: application/json' -d @- | python -mjson.tool) <<EOF
{
"entities": [
{
"type": "Room",
"isPattern": "false",
"id": "Room1"
}
],
"attributes": [
"temperature"
]
}
EOF
We can update an specific instance (e.g. ground), letting the other untouched:
(curl localhost:1026/v1/updateContext -s -S --header 'Content-Type: application/json' \
--header 'Accept: application/json' -d @- | python -mjson.tool) <<EOF
{
"contextElements": [
{
"type": "Room",
"isPattern": "false",
"id": "Room1",
"attributes": [
{
"name": "temperature",
"type": "float",
"value": "30",
"metadatas": [
{
"name": "ID",
"type": "string",
"value": "ground"
}
]
}
]
}
],
"updateAction": "UPDATE"
}
EOF
Check it using again queryContext (ground has changed to 30ºC but wall has its initial value of 23.8º C).
To avoid ambiguities, you cannot mix the same attribute with and without ID. The following entity creation will fail:
(curl localhost:1026/v1/updateContext -s -S --header 'Content-Type: application/json' \
--header 'Accept: application/json' -d @- | python -mjson.tool) <<EOF
{
"contextElements": [
{
"type": "Room",
"isPattern": "false",
"id": "Room1",
"attributes": [
{
"name": "temperature",
"type": "float",
"value": "23.5",
"metadatas": [
{
"name": "ID",
"type": "string",
"value": "ground"
}
]
},
{
"name": "temperature",
"type": "float",
"value": "23.8"
}
]
}
],
"updateAction": "APPEND"
}
EOF
...
{
"statusCode": {
"code": "472",
"details": "action: APPEND - entity: (Room1, Room) - offending attribute: temperature",
"reasonPhrase": "request parameter is invalid/not allowed"
}
}
...
Finally, you can use also the following convenience operations with attributes using ID metadata:
- GET /v1/contextEntities/Room1/attributes/temperature/ground: to get an specific attribute identified by ID
- PUT /v1/contextEntities/Room1/attributes/temperature/ground (using as payload updateContextElementRequest, as described in a previous section).
- DELETE /v1/contextEntities/Room1/attributes/temperature/ground: to remove an specific attribute identified by ID (see DELETE attribute semantics described in a previous section).
Metadata in notifications
By default, all custom (user) metadata are included in notifications. However, the field metadata
can be used to filter the list. In addition, it can be used to specify that the following special
metadata (not included by default) must be included.
- previousValue
- actionType
Details about their meaning can be found in the ""System/builtin in metadata"" section in the NGSIv2 specification.
Note that using the following
"metadata": [ "previousValue" ]
will cause to include previousValue
but will exclude user metadata that
attributes in the notification may have. If you want to get previousValue
and any other "regular" metadata then use:
"metadata": [ "previousValue", "*" ]
Note that you can also use "metadata": [ "*" ]
although it doesn't make much sense, as
it gives the same result as not including metadata
at all (remember that the default
behaviour is to include all user metadata).
See details in "Filtering out attributes and metadata" section in the NGSIv2 specification.