Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Switch services using the Version drop-down list. Learn more about navigation.
Applies to: ✅ Azure Data Explorer
openCypher is an open-source specification for querying property graph databases. You can now run openCypher queries on KQL graph semantics, using a declarative syntax with ASCII-art style pattern matching that makes it intuitive to express complex graph patterns and relationships.
Note
openCypher support is in preview. Features and syntax can change based on feedback and ongoing development.
Getting started
To use openCypher, you need:
- A graph data source that's either a graph model or a function returning a transient graph ending with a make-graph operator (see step 1)
- Set specific client request properties (see step 2)
Step 1: Create a graph reference
Before you use openCypher, create a graph data source. This article uses an in-memory make-graph operator, but we recommend using a graph snapshot for production scenarios.
.create-or-alter function G_doc() {
let nodes = datatable(id:string, lbl:string, name:string, properties:dynamic)
[
"p1","Person","Alice",dynamic({"age": 25}),
"p2","Person","Bob",dynamic({"age": 30}),
"p3","Person","Carol",dynamic({"age": 28}),
"p4","Person","David",dynamic({"age": 35}),
"p5","Person","Emma",dynamic({"age": 26}),
"c1","Company","TechCorp",,
"c2","Company","DataSoft",,
"c3","Company","CloudInc",,
"ct1","City","Seattle",,
"ct2","City","Portland",,
"ct3","City","San Francisco",
];
let edges = datatable(source:string, target:string, lbl:string, since:int)
[
"p1","c1","works_at",2020,
"p2","c1","works_at",2022,
"p3","c2","works_at",2023,
"p4","c3","works_at",2021,
"p5","c1","works_at",2024,
"p1","ct1","located_at",2019,
"p2","ct1","located_at",2021,
"p3","ct2","located_at",2022,
"p4","ct3","located_at",2020,
"p5","ct2","located_at",2023,
"c1","ct1","located_at",2015,
"c2","ct2","located_at",2018,
"c3","ct3","located_at",2017,
"p1","p2","knows",2019,
"p2","p3","knows",2021,
"p3","p4","knows",2022,
"p4","p5","knows",2023,
"p1","p4","likes",2020,
"p4","p1","likes",2020,
"p5","p2","likes",2022
];
edges
| make-graph source --> target with nodes on id
}
Step 2: Configure client request properties
To run openCypher queries, set three client request properties. Set these properties through the SDK, API, or directly in the Kusto Explorer or Azure Data Explorer web UI by using directives.
Set client request properties
Important
Run each directive separately before you run your openCypher query. The directives set up the query environment for openCypher execution.
#crp query_language=opencypher
#crp query_graph_reference=G_doc()
To use labels in openCypher, set the label column name:
#crp query_graph_label_name=lbl
Tip
Labels are optional in openCypher, but they're often used to filter nodes and edges by type. Set the label column name to use labels in your openCypher queries.
Set client request properties programmatically
For programmatic access, set these client request properties:
query_language: Set to"opencypher".query_graph_reference: Set to your graph function name (for example,"G_doc()").query_graph_label_name: Set to your label column name (for example,"lbl").
Step 3: Run openCypher queries
After you finish setup, run openCypher queries using the standard syntax. Use the examples below to explore basic openCypher features.
Examples
The following examples demonstrate core openCypher query patterns. openCypher uses ASCII-art style syntax where nodes are represented in parentheses () and relationships in square brackets [] with arrows --> or <-- to indicate direction.
Example 1: Basic pattern matching
Find all relationships in the graph and count them.
MATCH (n)-[e]->(n2)
RETURN COUNT(*) as CNT
Output
The following table shows the result of the query.
| CNT |
|---|
| 20 |
This query matches any node n connected to another node n2 through a relationship e and returns the total count of such patterns.
Example 2: Pattern matching with labels
Find people and their connections, filtering by node labels.
MATCH (p:Person)-[e]->(target)
RETURN p.name, target.name, e.lbl
ORDER BY p.name, target.name
LIMIT 2
Output
The following table shows the result of the query.
| p.name | target.name | e.lbl |
|---|---|---|
| Alice | Bob | knows |
| Alice | David | likes |
This query finds all Person nodes and returns their names, the names of connected nodes, and the relationship type. The :Person label filters the source node to only match Person nodes.
Example 3: Filtering with WHERE clause
Find people over 25 years old and return their details.
MATCH (person:Person)
WHERE person.properties.age > 25
RETURN person.name, person.properties.age
ORDER BY person.name
Output
| person.name | person.properties.age |
|---|---|
| Bob | 30 |
| Carol | 28 |
| David | 35 |
| Emma | 26 |
This query demonstrates property filtering using the WHERE clause to find people whose age property is greater than 25.
Example 4: Variable length paths
Find all persons reachable from Alice through 1 to 3 hops.
MATCH (center)-[*1..3]->(connected:Person)
WHERE center.name = 'Alice'
RETURN DISTINCT connected.name
ORDER BY connected.name
Output
| connected.name |
|---|
| Alice |
| Bob |
| Carol |
| David |
| Emma |
This query uses variable length paths [*1..3] to find all persons reachable from Alice through one to three hops. The DISTINCT keyword ensures each connected node appears only once.
Example 5: Aggregation and grouping
Count how many people work at each company.
MATCH (person:Person)-[:works_at]->(company:Company)
RETURN company.name AS Company, COUNT(person) AS EmployeeCount
ORDER BY EmployeeCount DESC
Output
| Company | EmployeeCount |
|---|---|
| TechCorp | 3 |
| CloudInc | 1 |
| DataSoft | 1 |
This query demonstrates aggregation by grouping people by their company and counting employees at each company. The [:works_at] syntax filters relationships by type.
Limitations
openCypher support has the following limitations:
Query structure: All openCypher queries must start with a
MATCHstatement.Unsupported language constructs: The following openCypher language constructs are not currently supported:
- WITH clause: Not supported for query composition
- Subqueries: Including
EXISTSsubqueries and pattern predicates
Unsupported keywords: The following openCypher keywords are not supported:
MANDATORY MATCHUNWINDUNIONSKIP
Unsupported scalar functions: The following openCypher scalar functions are not yet implemented:
- Mathematical functions:
sin(),cos(),tan(),log(),round(),sign(),rand() - Statistical functions:
percentileDisc(),percentileCont(),stDev(),stDevP() - Utility functions:
coalesce(),id(),properties(),type(),range() - Case expressions:
CASEstatements
- Mathematical functions:
Partial support:
CALLprocedures have only partial support.Reserved keywords: Some openCypher keywords can't be used as identifiers in queries. Some reserved keywords aren't immediately obvious. If your graph data has property names that conflict with openCypher reserved keywords, use different property names in your graph schema or rename them to avoid parsing conflicts.
Important
When you design your graph schema, some common property names might conflict with openCypher reserved keywords. Avoid or rename these property names.
No graph modification operations: Operations to change graph structures (such as
CREATE,MERGE,DELETE,SET,REMOVE) are not supported. Use KQL for all graph creation, change, and management tasks.Optional pattern matching:
OPTIONAL MATCHis supported only for node patterns, not for edge patterns.Entity equivalence checks: Entity equivalence checks using operators like
=or<>between nodes or relationships (for example,MATCH (n)-[]-(m) WHERE n <> m) are not supported. Use explicit field comparisons instead, such asn.id <> m.id.Time and timezone: The engine operates in UTC. Datetime literals must use appropriate formats; only the UTC timezone is supported.