-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #30 from FalkorDB/split-cypher-documentation
split cypher documentation
- Loading branch information
Showing
25 changed files
with
1,791 additions
and
1,636 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
--- | ||
title: "Algorithms" | ||
nav_order: 19 | ||
description: > | ||
FalkorDB implements a subset of the Cypher language, which is growing as development continues. | ||
parent: "Cypher Language" | ||
--- | ||
|
||
# Algorithms | ||
|
||
## BFS | ||
|
||
The breadth-first-search algorithm accepts 3 arguments: | ||
|
||
`source-node (node)` - The root of the search. | ||
|
||
`max-level (integer)` - If greater than zero, this argument indicates how many levels should be traversed by BFS. 1 would retrieve only the source's neighbors, 2 would retrieve all nodes within 2 hops, and so on. | ||
|
||
`relationship-type (string)` - If this argument is NULL, all relationship types will be traversed. Otherwise, it specifies a single relationship type to perform BFS over. | ||
|
||
It can yield two outputs: | ||
|
||
`nodes` - An array of all nodes connected to the source without violating the input constraints. | ||
|
||
`edges` - An array of all edges traversed during the search. This does not necessarily contain all edges connecting nodes in the tree, as cycles or multiple edges connecting the same source and destination do not have a bearing on the reachability this algorithm tests for. These can be used to construct the directed acyclic graph that represents the BFS tree. Emitting edges incurs a small performance penalty. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
--- | ||
title: "CALL clause" | ||
nav_order: 16 | ||
description: > | ||
FalkorDB implements a subset of the Cypher language, which is growing as development continues. | ||
parent: "Cypher Language" | ||
--- | ||
|
||
# CALL \{\} | ||
|
||
The CALL {} (subquery) clause allows local execution of subqueries, which opens the door for many comfortable and efficient actions on a graph. | ||
|
||
The subquery is executed once for each record in the input stream. | ||
|
||
The subquery may be a returning or non-returning subquery. A returning subquery may change the amount of records, while a non-returning subquery will not. | ||
|
||
The variables in the scope before the CALL {} clause are available after the clause, together with the variables returned by the subquery (in the case of a returning subquery). | ||
|
||
Variables may be imported from the outer scope **only** in an opening `WITH` clause, via simple projections (e.g. `WITH n, m`), or via `WITH *` (which imports all bound variables). The variables returned from a subquery may not override existing variables in the outer scope. | ||
|
||
The CALL {} clause may be used for numerous purposes, such as: Post-`UNION` processing, local environment for aggregations and actions on every input row, efficient operations using a limited namespace (via imports) and performing side-effects using non-returning subqueries. Let's see some examples. | ||
|
||
* Post-`UNION` processing. | ||
|
||
We can easily get the cheapest and most expensive items in a store and set their `of_interest` property to `true` (to keep monitoring the 'interesting' items) using post-`UNION` processing: | ||
|
||
```sh | ||
GRAPH.QUERY DEMO_GRAPH | ||
CALL { | ||
MATCH (s:Store {name: 'Walmart'})-[:SELLS]->(i:Item) | ||
RETURN i AS item | ||
ORDER BY price ASC | ||
LIMIT 1 | ||
UNION | ||
MATCH (s:Store {name: 'Walmart'})-[:SELLS]->(i:Item) | ||
RETURN i AS item | ||
ORDER BY price DESC | ||
LIMIT 1 | ||
} | ||
SET item.of_interest = true | ||
RETURN item.name AS name, item.price AS price | ||
``` | ||
|
||
We can utilize post-`UNION` processing to perform aggregations over differently-matched entities. For example, we can count the number of customers and vendors that a store interacts with: | ||
|
||
```sh | ||
GRAPH.QUERY DEMO_GRAPH | ||
CALL { | ||
MATCH (s:Store {name: 'Walmart'})-[:SELLS_TO]->(c:Customer) | ||
RETURN c AS interface | ||
UNION | ||
MATCH (s:Store {name: 'Walmart'})-[:BUYS_FROM]->(v:Vendor) | ||
RETURN v AS interface | ||
} | ||
RETURN count(interface) AS interfaces | ||
``` | ||
|
||
* Local environment for aggregations and actions on every input row. | ||
|
||
Another key feature of the CALL {} clause is the ability to perform isolated aggregations on every input row. For example, let's check if there is any correlation between the amount of sales per-product and the advertisement-intensity implemented for it in a particular month. | ||
|
||
```sh | ||
GRAPH.QUERY DEMO_GRAPH | ||
MATCH (item:Item) | ||
CALL { | ||
WITH item | ||
MATCH (item)-[s:SOLD_TO {advertisement_intensity: 10}]->(c:Customer) | ||
WHERE s.date > '01-01-2023' AND s.date < '01-02-2023' | ||
RETURN count(s) AS item_sales_ads_high | ||
} | ||
CALL { | ||
WITH item | ||
MATCH (item)-[s:SOLD_TO {advertisement_intensity: 5}]->(c:Customer) | ||
WHERE s.date > '01-01-2023' AND s.date < '01-02-2023' | ||
RETURN count(s) AS item_sales_ads_low | ||
} | ||
RETURN item.name AS name, item_sales_ads_high as high_ads_sales, item_sales_ads_low as low_ads_sales | ||
``` | ||
|
||
<!-- * Observe changes from previous executions (on previous records). | ||
We can form useful structures and connections like linked-lists via the CALL {} clause. Let's form a linked-list of all items in a store, from the cheapest to the priciest: | ||
```sh | ||
MATCH (i:Item) | ||
WITH i order BY i.price ASC LIMIT 1 | ||
SET i:HEAD | ||
WITH i | ||
MATCH (next_item:Item) WHERE NOT next_item:HEAD | ||
WITH next_item ORDER BY next_item.price ASC | ||
CALL { | ||
WITH next_item | ||
MATCH (curr_head:HEAD) | ||
REMOVE curr_head:HEAD | ||
SET next_item:HEAD | ||
CREATE (curr_head)-[:IS_CHEAPER_THAN]->(next_item) | ||
} | ||
``` --> | ||
|
||
<!-- This will be added to a "performance-enhancement" section in the near future. | ||
* Efficient operations using a limited namespace (via imports). | ||
Given a query holding a respectively large namespace (a lot of bound variables), we can execute a subquery on a sub-namespace, and by thus enhance performance significantly. Let's look at an example. | ||
Without a CALL {} clause: | ||
```sh | ||
GRAPH.QUERY DEMO_GRAPH | ||
"MATCH (n:N), (m:M), (x:X), (y:Y), (z:Z), (e:E), (q:Q) | ||
MATCH (temp:TEMP) | ||
SET temp.v = n.v | ||
RETURN n, m, x, y, z, e, q" | ||
``` | ||
Runtime: 256 ms. | ||
With a CALL {} clause: | ||
```sh | ||
GRAPH.QUERY DEMO_GRAPH | ||
"MATCH (n:N), (m:M), (x:X), (y:Y), (z:Z), (e:E), (q:Q) | ||
CALL { | ||
WITH n | ||
MATCH (temp:TEMP) | ||
SET temp.v = n.v | ||
} | ||
RETURN n, m, x, y, z, e, q" | ||
``` | ||
Runtime: 99 ms. --> | ||
|
||
* Side-effects. | ||
|
||
We can comfortably perform side-effects using non-returning subqueries. For example, we can mark a sub-group of nodes in the graph withholding some shared property. Let's mark all the items in a Walmart store that were sold more than 100 times as popular items, and return **all** items in the store: | ||
|
||
```sh | ||
GRAPH.QUERY DEMO_GRAPH | ||
MATCH (item:Item) | ||
CALL { | ||
WITH item | ||
MATCH (item)-[s:SOLD_TO]->(c:Customer) | ||
WITH item, count(s) AS item_sales | ||
WHERE item_sales > 100 | ||
SET item.popular = true | ||
} | ||
RETURN item | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
--- | ||
title: "CREATE clause" | ||
nav_order: 8 | ||
description: > | ||
FalkorDB implements a subset of the Cypher language, which is growing as development continues. | ||
parent: "Cypher Language" | ||
--- | ||
|
||
# CREATE | ||
|
||
CREATE is used to introduce new nodes and relationships. | ||
|
||
The simplest example of CREATE would be a single node creation: | ||
|
||
```sh | ||
CREATE (n) | ||
``` | ||
|
||
It's possible to create multiple entities by separating them with a comma. | ||
|
||
```sh | ||
CREATE (n),(m) | ||
``` | ||
|
||
```sh | ||
CREATE (:Person {name: 'Kurt', age: 27}) | ||
``` | ||
|
||
To add relations between nodes, in the following example we first find an existing source node. After it's found, we create a new relationship and destination node. | ||
|
||
```sh | ||
GRAPH.QUERY DEMO_GRAPH | ||
"MATCH (a:Person) | ||
WHERE a.name = 'Kurt' | ||
CREATE (a)-[:MEMBER]->(:Band {name:'Nirvana'})" | ||
``` | ||
|
||
Here the source node is a bounded node, while the destination node is unbounded. | ||
|
||
As a result, a new node is created representing the band Nirvana and a new relation connects Kurt to the band. | ||
|
||
Lastly we create a complete pattern. | ||
|
||
All entities within the pattern which are not bounded will be created. | ||
|
||
```sh | ||
GRAPH.QUERY DEMO_GRAPH | ||
"CREATE (jim:Person{name:'Jim', age:29})-[:FRIENDS]->(pam:Person {name:'Pam', age:27})-[:WORKS]->(:Employer {name:'Dunder Mifflin'})" | ||
``` | ||
|
||
This query will create three nodes and two relationships. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
--- | ||
title: "Cypher Language" | ||
nav_order: 7 | ||
description: > | ||
FalkorDB implements a subset of the Cypher language, which is growing as development continues. | ||
has_children: true | ||
--- | ||
|
||
# Clauses | ||
|
||
Cypher query consists of one or more clauses | ||
|
||
* [MATCH](/cypher/match) | ||
* [OPTIONAL MATCH](/cypher/optional_match) | ||
* [WHERE](/cypher/where) | ||
* [RETURN](/cypher/return) | ||
* [ORDER BY](/cypher/order_by) | ||
* [SKIP](/cypher/skip) | ||
* [LIMIT](/cypher/limit) | ||
* [CREATE](/cypher/create) | ||
* [MERGE](/cypher/merge) | ||
* [DELETE](/cypher/delete) | ||
* [SET](/cypher/set) | ||
* [WITH](/cypher/with) | ||
* [UNION](/cypher/union) | ||
* [UNWIND](/cypher/unwind) | ||
* [FOREACH](/cypher/foreach) | ||
* [CALL {}](/cypher/call) | ||
|
||
# Functions | ||
|
||
See list of available [Functions](/cypher/functions) | ||
|
||
# Procedures | ||
|
||
See list of available [Procedures](/cypher/procedures) | ||
|
||
# Algorithms | ||
|
||
See list of available graph [Algorithms](/cypher/algorithms) | ||
|
||
# Indexing | ||
|
||
See how to utilize [Indexing](/cypher/index) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
--- | ||
title: "DELETE clause" | ||
nav_order: 9 | ||
description: > | ||
FalkorDB implements a subset of the Cypher language, which is growing as development continues. | ||
parent: "Cypher Language" | ||
--- | ||
|
||
# DELETE | ||
|
||
DELETE is used to remove both nodes and relationships. | ||
|
||
Note that deleting a node also deletes all of its incoming and outgoing relationships. | ||
|
||
To delete a node and all of its relationships: | ||
|
||
```sh | ||
GRAPH.QUERY DEMO_GRAPH "MATCH (p:Person {name:'Jim'}) DELETE p" | ||
``` | ||
|
||
To delete relationship: | ||
|
||
```sh | ||
GRAPH.QUERY DEMO_GRAPH "MATCH (:Person {name:'Jim'})-[r:FRIENDS]->() DELETE r" | ||
``` | ||
|
||
This query will delete all `friend` outgoing relationships from the node with the name 'Jim'. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
--- | ||
title: "FOREACH clause" | ||
nav_order: 15 | ||
description: > | ||
FalkorDB implements a subset of the Cypher language, which is growing as development continues. | ||
parent: "Cypher Language" | ||
--- | ||
|
||
# FOREACH | ||
|
||
The `FOREACH` clause feeds the components of a list to a sub-query comprised of **updating clauses only** (`CREATE`, `MERGE`, `SET`, `REMOVE`, `DELETE` and `FOREACH`), while passing on the records it receives without change. | ||
|
||
The clauses within the sub-query recognize the bound variables defined prior to the `FOREACH` clause, but are local in the sense that later clauses are not aware of the variables defined inside them. In other words, `FOREACH` uses the current context, and does not affect it. | ||
|
||
The `FOREACH` clause can be used for numerous purposes, such as: Updating and creating graph entities in a concise manner, marking nodes\edges that satisfy some condition or are part of a path of interest and performing conditional queries. | ||
|
||
We show examples of queries performing the above 3 use-cases. | ||
|
||
The following query will create 5 nodes, each with property `v` with the values from 0 to 4 corresponding to the appropriate index in the list. | ||
|
||
```sh | ||
GRAPH.QUERY DEMO_GRAPH | ||
"FOREACH(i in [1, 2, 3, 4] | CREATE (n:N {v: i}))" | ||
``` | ||
|
||
The following query marks the nodes of all paths of length up to 15 km from a hotel in Toronto to a steakhouse with at least 2 Michelin stars. | ||
|
||
```sh | ||
GRAPH.QUERY DEMO_GRAPH | ||
"MATCH p = (hotel:HOTEL {City: 'Toronto'})-[r:ROAD*..5]->(rest:RESTAURANT {type: 'Steakhouse'}) WHERE sum(r.length) <= 15 AND hotel.stars >= 4 AND rest.Michelin_stars >= 2 | ||
FOREACH(n in nodes(p) | SET n.part_of_path = true)" | ||
``` | ||
|
||
The following query searches for all the hotels, checks whether they buy directly from a bakery, and if not - makes sure they are marked as buying from a supplier that supplies bread, and that they do not buy directly from a bakery. | ||
|
||
```sh | ||
GRAPH.QUERY DEMO_GRAPH | ||
"MATCH (h:HOTEL) OPTIONAL MATCH (h)-[b:BUYS_FROM]->(bakery:BAKERY) | ||
FOREACH(do_perform IN CASE WHEN b = NULL THEN [1] ELSE [] END | MERGE (h)-[b2:BUYS_FROM]->(s:SUPPLIER {supplies_bread: true}) SET b2.direct = false)" | ||
``` |
Oops, something went wrong.