Search
On this page we'll cover how to search with the IOTICS API's Search Service.
Using the Search Service allows you to run a synchronous GLOBAL
or LOCAL
search with each available result returned as a chunk. The last chunk will always be a timeout error.
Any user of IOTICS can run a semantic search to find metadata and data feeds both inside their own IOTICSpace and outside, in the IOTICS ecosystem. The search will find and return all Digital Twins matching the set criteria that the user has permission to access.
You can search loosely, such as for text or location, or more specific, such as by specifying exact semantic triple matches.
Once you've found a Twin that matches your criteria you can use the Twin Service to Describe it, see our Twin guide for more information.
On this page we will cover how to:
You can see the entire IOTICS API Reference here.
Set your headers
The headers are an important part of your API request, representing the meta-data of your request. Before submitting a request you need to ensure you have set your headers:
Header | Type | Description | Mandatory |
---|---|---|---|
Iotics-ClientRef | String | Any responses associated with the request will include this reference | Optional |
Iotics-ClientAppId | String | User namespace used to group all the requests/responses | Mandatory |
Iotics-TransactionRef | String | Used to loosely link requests/responses in a distributed environment each layer can add its own id to the list Limited to: - max 16 elements per list - max 36 characters | Optional |
Iotics-RequestTimeout | String (Date-Time) | Used to stop request processing once timeout value is reached | Mandatory |
The request
To search, you just submit a search POST
to the IOTICS API's Search service.
You can see an example request here.
Query parameters
You first set the parameters of your query, deciding the scope of your search and how many results to return:
Parameter | Type | Description |
---|---|---|
lang | String | Language code for properties |
scope | String | Choose from: - GLOBAL - LOCAL - LOCAL_OWN - AUTO |
limit | Int64 | Limits amount of results returned. Default = 500 Maximum = 1000 |
offset | Int64 | Sets where the results are returned from, used with limit to control what is returned |
Body parameters
You then set the payload for your request, made up of:
Parameter | Type | Description |
---|---|---|
expiryTimeout | String (Date-Time) | UTC time for when the search request will expire |
filter | Object | Used to filter your results |
filter:location | Object | Use to filter by location |
filter:location:location | Object | The location being filtered by |
filter:location:location:lat | Double | The latitude of the location being filtered by |
filter:location:location:lon | Double | The longitude of the location being filtered by |
filter:location:location:radiusKm | Double | The radius in km around the location to be filtered by |
filter:properties | Array of objects | Used to filter Twin properties |
filter:properties:key | String | Filter with the key (predicate) of the properties |
filter:properties:key:langLiteralValue | Object | Use a langLiteralValue to filter for a property |
filter:properties:key:langLiteralValue:lang | String | The 2- character language code for the property |
filter:properties:key:langLiteralValue:value | String | The value of the property you're filtering by |
filter:properties:key:literalValue | Object | Use a literalValue to filter by a property |
filter:properties:key:literalValue:dataType | String | XSD data type. Currently supports: dateTime, time, date, boolean, integer, nonPositiveInteger, negativeInteger, nonNegativeInteger, positiveInteger, long, unsignedLong, int, unsignedInt, short, unsignedShort, byte, unsignedByte, anyURI |
filter:properties:key:literalValue:value | String | String representation of the value according to XSD datatype specification |
filter:properties:key:stringLiteralValue | Object | Use a stringLiteralValue to filter by a property |
filter:properties:key:stringLiteralValue:value | String | The value of the property you're filtering by |
filter:properties:key:uriValue | Object | Use a URI to filter by a property |
filter:properties:key:uriValue:value | String | The value of the property you're filtering by |
filter:text | String | One or more keywords which must match text from entity Note: Any, rather than all, of the keywords will produce a match |
responseType | String | Choose from: - FULL - LOCATED - MINIMAL |
Examples
Example Search Request
This is an example of a request to search for looking for all Weather related Twins within 3km of central Cambridge.
You can build your own example by going to the Search Service reference page.
# REQUIREMENTS:
# Create a python venv and activate it
# pip install -U pip setuptools wheel
# pip install iotics-identity
# USER_KEY_NAME, AGENT_KEY_NAME, USER_SEED, AGENT_SEED
import json
from datetime import datetime, timedelta, timezone
from typing import List
from uuid import uuid4
from iotics.lib.identity.api.high_level_api import get_rest_high_level_identity_api
from requests import request
RESOLVER_URL = "resolver_url"
HOST = "host_url"
USER_KEY_NAME = "user_key_name"
AGENT_KEY_NAME = "agent_key_name"
USER_SEED = bytes.fromhex("user_seed")
AGENT_SEED = bytes.fromhex("agent_seed")
def search_twins(
headers: dict,
properties: List[dict] = None,
text: str = None,
location: dict = None,
scope: str = "GLOBAL",
response_type: str = "FULL",
):
payload = {"filter": {}, "responseType": response_type}
if properties:
payload["filter"]["properties"] = properties
if text:
payload["filter"]["text"] = text
if location:
payload["filter"]["location"] = location
twins_list = [] # Initialise an empty list
with request(
method="POST",
url=f"{HOST}/qapi/searches",
headers=headers,
json=payload,
stream=True,
verify=False,
params={"scope": scope},
) as resp:
# Raises HTTPError, if one occurred
resp.raise_for_status()
# Iterates over the response data, one line at a time
for chunk in resp.iter_lines():
response = json.loads(chunk)
twins_found = []
try:
host_id = response["result"]["payload"]["remoteHostId"]["value"]
twins_found = response["result"]["payload"]["twins"]
except KeyError:
host_id = "local"
else:
if twins_found:
# Add the host id value to each twin
for twin in twins_found:
twin["HostId"] = host_id
# Append the twins found to the list of twins
twins_list.extend(twins_found)
return twins_list
def create_headers(client_app_id: uuid4, token: str, request_timeout: str):
return {
"accept": "application/json",
"Iotics-ClientAppId": f"search_{client_app_id}",
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
"Iotics-RequestTimeout": request_timeout,
}
def create_property_dict(property_key: str, property_value: str, property_type: str):
return {"key": property_key, property_type: {"value": property_value}}
def create_location_dict(lat: float, lon: float, radius_km: float):
return {
"location": {"lon": lon, "lat": lat},
"radiusKm": radius_km,
}
api = get_rest_high_level_identity_api(resolver_url=RESOLVER_URL)
(
user_registered_id,
agent_registered_id,
) = api.create_user_and_agent_with_auth_delegation(
user_seed=USER_SEED,
user_key_name=USER_KEY_NAME,
agent_seed=AGENT_SEED,
agent_key_name=AGENT_KEY_NAME,
delegation_name="#AuthDeleg",
)
twins_list = search_twins(
headers=create_headers(
client_app_id=uuid4(),
token=api.create_agent_auth_token(
agent_registered_identity=agent_registered_id,
user_did=user_registered_id.did,
duration=30,
),
request_timeout=(
datetime.now(tz=timezone.utc) + timedelta(seconds=10)
).isoformat(),
),
properties=[
create_property_dict(
property_key="http://data.iotics.com/public#hostAllowList",
property_type="uriValue",
property_value="http://data.iotics.com/public#allHosts",
)
],
location=create_location_dict(lat=52.205276, lon=0.119167, radius_km=3),
text="Weather",
)
print(f"{len(twins_list)} twins found")
print("---")
for twin in twins_list:
print(json.dumps(twin, indent=4))
print("---")
Updated about 2 years ago