To enable a user friendly query language, we provide one based on Cypher (https://neo4j.com/developer/cypher/). We use it only for search and not for creation.
We made some adaptations to fit to the Thing'in data model. Here we list the more outstanding rules of translation.
Be carrefull to use single quote
`
and not'
or you will have syntax error.
We provide a fragment of the Cypher query language, which means we haven't included all aspects of the language's capabilities.
This page focuses on the semantics of Cypher. The conversion between TiQL and Cypher can be found in TiQLToCypher.
You can use POST /avatars/find to make Cypher for Thing'in query, using the cypher
key instead of query
For example:
{
"cypher":"MATCH ..."
}
In Cypher nodes have labels and can be filtered according to them. In Thing'in, two concepts can fit this requirements : classes and labels. Then in Cypher for Thing'in you can use both as labels.
Remember that, Cypher labels starting with
http://
orhttps://
are translated to classes.
TiQL
{
"$classes" : {"$contains" : "UNE_CLASSE"}
}
Cypher query
MATCH (:`UNE_CLASSE`)
RETURN *
TiQL
{
"$label" : {"$contains" : "UN_LABEL"}
}
Cypher query
MATCH (:`UN_LABEL`)
RETURN *
TiQL
{
"$classes" : {"$contains" : "UNE_CLASSE"},
"$label" : {"$contains" : "UN_LABEL"}
}
Cypher query
MATCH (:`UNE_CLASSE`:`UN_LABEL`)
RETURN *
Find the avatar with the given IRI
Cypher query
MATCH ({iri:`IRI`})
RETURN *
Find the avatars with multiple constraints
Cypher for Thing'in
MATCH (a:`UN_LABEL` {domain:`MON_DOMAIN`})
WHERE a.visibility >= 0
RETURN *
Graph pattern matching forms the fundamental foundation of Cypher. It constitutes the technique employed for traversing, describing, and retrieving data from a graph structure using the MATCH
clause.
A graph pattern is a representation of data that closely resembles how nodes and relationships are drawn on a whiteboard. In Cypher, nodes are symbolized by pairs of parentheses, while relationships are indicated using dashes and greater-than or less-than symbols (e.g., () -[]-> ()
).
Find the rooms (ontology concept
ROOM
) that are in (ontology conceptisIn
) a building having an iriB_IRI
Cypher query
MATCH ({iri:`B_IRI`})-[:isIn]->(r:ROOM)
RETURN r
Find the sensors connected to a device D_IRI between 8:00 and 12:00
Cypher query
MATCH (s:SENSOR)-[c:CONNECTED_TO]->({iri:`D_IRI`})
WHERE c.START_TIME >= 0 AND c.END_TIME <= 12
RETURN s
The relationship directionality is supported using the symbols <
and >
to create arrows.
When a relationship pattern lacks arrows, it will match relationships of any direction.
We support the following Cypher's relationship direction constructs:
-[]-
: any direction.-[]->
: outgoing direction.<-[]-
: incoming direction.You can directly incorporate constraints on relationship properties within the relationship pattern, like this: ()-[r:{property_x: value_x, property_y: value_y}]->()
. Although this can also be achieved using the WHERE
subclause, integrating it within the relationship pattern reduces query verbosity.
Find the sensors connected to a device via MQTT protocol and for a duration of 4 minutes.
Cypher query
MATCH (s:SENSOR) -[r:CONNECTED_TO { protocol: 'MQTT', duration: 'PT4M' }]-> (d:DEVICE)
RETURN s
You also have the option to include complex relationship constraints using the embedded WHERE subclause, which can be formulated as ()-[r WHERE boolean_expression]-()
. Here, the boolean_expression
encompasses the constraints on the relationship r
. While you can provide such constraints using the WHERE subclause after the MATCH clause, embedding them directly within the relationship pattern enhances clarity and reduces verbosity.
Find the sensors connected to a device via MQTT protocol and for a duration shorter than 4 minutes.
Cypher query
MATCH (s:SENSOR) -[r:CONNECTED_TO WHERE r.protocol: 'MQTT' AND r.duration < 'PT4M']-> (d:DEVICE)
RETURN s
We support the following Cypher's depth constructs:
*n
: exactly n relationships.*m..n
: between m and n relationships.*..n
: between 1 and n relationships.Note that Cypher could present additional alternatives for variable-length relationships like * and *m... Nevertheless, these won't be converted here due to our restriction on infinite path depths.
Find the sensors that are connected to a device via a path of depth 2.
Cypher query
MATCH (s:SENSOR) -[r:connectedTo*..2]- (d:DEVICE)
RETURN s
All valid paths start and end with a node, linked by relationships if multiple nodes are involved. Besides, they must contain at least one node pattern and maintain an alternating sequence of nodes and relationships like: (n1)-[r1]->(n2)-[r2]->(n3)
or (n1)-[r1]->(n2), (n1)-[r2]->(n3)
.
Find sensors that are connected to a device located in a room X.
Cypher query
MATCH (s:SENSOR) -[r:CONNECTED_TO]-> (d:DEVICE) -[i:isIn]-> (ro:ROOM)
WHERE ro.IRI = 'X'
RETURN s
Find sensors that are located in room X and connected to a device.
Cypher query
MATCH (s:SENSOR) -[r:CONNECTED_TO]-> (d:DEVICE), (s) -[i:isIn]-> (ro:ROOM)
WHERE ro.IRI = 'X'
RETURN s
The OPTIONAL MATCH
clause is used to retrieve nodes and relationships based on a pattern, but unlike the regular MATCH
clause, it allows for the possibility of not finding a match. In other words, if the pattern specified in the OPTIONAL MATCH
clause does not match any nodes or relationships in the graph, the query will still return the result of the preceding MATCH
clause.
For example, consider a graph where some nodes have a relationship with a given label "CONNECTED_TO," while others do not. With an OPTIONAL MATCH
on the "CONNECTED_TO" relationship, the query will return all nodes, and if the relationship exists, it will be included in the result. If the relationship does not exist, the query result will still include the node, without the relationship part.
Find nodes labeled as "head" with a specific domain. Then, optionally look for a relationship labeled "hasRouterLink" between that node and another node labeled "tail" with a certain property value. If the relationship and the property match are found, it returns the "head" node. If not, it still returns the "head" node without the relationship.
Cypher query
MATCH (head {domain: 'http://www.example.com/optional/'})
OPTIONAL MATCH (head)-[r1: `http://www.disit.org/km4city/schema#hasRouterLink`]->
(tail {`http://knoesis.wright.edu/ssw/ont/sensor-observation.owl#distance` : 300.0})
RETURN head
This section contains an overview of the Cypher's operators supported in Thing'in.
Overview of operators :
The arthimetic operators incldue:
+
: addition-
: subtraction or unary minus*
: multiplication/
: division%
: modulo division^
: exponentiationFind the sensors for which the sum of properties x and y exceeds 3.
Cypher query
MATCH (s:SENSOR)
WHERE s.x + s.y > 3
RETURN s
String-specific comparison operators include:
STARTS WITH
: searching for the beginning of a string in a case-sensitive manner.ENDS WITH
: searching for the end of a string in a case-sensitive manner.CONTAINS
: searching for a specific substring within a string, taking in a case sensitive manner.=~
: employing a regular expression to identify patterns within strings.Find the sensors connected to a device whose IRI starts with 'D'.
Cypher query
MATCH (s:SENSOR) -[:CONNECTED]-> (d:DEVICE)
WHERE d.IRI STARTS WITH 'D'
RETURN s
=
: equality<>
: inequality<
: less than>
: greater than<=
: less than or equal to>=
: greater than or equal toIS NULL
IS NOT NULL
Find sensors connected to a device with non-empty provider ID.
Cypher query
MATCH (s:SENSOR) -[:CONNECTED]-> (d:DEVICE)
WHERE d.PROVIDER_ID IS NOT NULL
RETURN s
IN
: checking if an element e exists in a list l (e IN [l]).Find sensors connected to an object containing 'Device' in its list of classes.
Cypher query
MATCH (s:SENSOR) -[:CONNECTED]-> (d)
WHERE 'DEVICE' IN d.classes
RETURN s
Keep in mind that the IN operator can be used in two ways:
'class_x' IN n.classes
) to check if the value class_x exists in the list property class.n.classes IN ['class_x', 'class_y']
) to check if the list property is included in the provided list value ['class_x', 'class_y'].AND
: conjunctionOR
: disjunctionFind sensors that are connected to devices whose provider IDs are either 'X' or 'Y'.
Cypher query
MATCH (s:SENSOR) -[:CONNECTED]-> (d:DEVICE)
WHERE d.PROVIDER_ID = 'x' OR d.PROVIDER_ID = 'y'
RETURN s