Skip to content

Commit

Permalink
Merge pull request #30 from FalkorDB/split-cypher-documentation
Browse files Browse the repository at this point in the history
split cypher documentation
  • Loading branch information
swilly22 authored Apr 9, 2024
2 parents a94060e + 9a6b583 commit 43bf2b9
Show file tree
Hide file tree
Showing 25 changed files with 1,791 additions and 1,636 deletions.
4 changes: 2 additions & 2 deletions _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ search_enabled: true
color_scheme: dark

aux_links:
"Docs Reposity":
"Docs Repository":
- "//github.com/falkordb/docs"
"FalkorDB Reposity":
"FalkorDB Repository":
- "//github.com/falkordb/falkordb"


Expand Down
1,634 changes: 1 addition & 1,633 deletions commands/graph.query.md

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions cypher/algorithms.md
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.
146 changes: 146 additions & 0 deletions cypher/call.md
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
```
51 changes: 51 additions & 0 deletions cypher/create.md
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.
44 changes: 44 additions & 0 deletions cypher/cypher.md
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)
3 changes: 2 additions & 1 deletion cypher_support.md → cypher/cypher_support.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
---
title: "Cypher coverage"
nav_order: 7
nav_order: 21
description: >
FalkorDB implements a subset of the Cypher language, which is growing as development continues.
parent: "Cypher Language"
---

This document is based on the Cypher Query Language Reference (version 9), available at [OpenCypher Resources](https://www.opencypher.org/resources).
Expand Down
27 changes: 27 additions & 0 deletions cypher/delete.md
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'.
40 changes: 40 additions & 0 deletions cypher/foreach.md
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)"
```
Loading

0 comments on commit 43bf2b9

Please sign in to comment.