Seraph.Query (Seraph v0.2.4)
Provide the query DSL.
Queries are used to retrieve and manipulate data from a repository (see Seraph.Repo
).
They can be written using keywords or macros.
Basic example:
# Keyword syntax
match [{n}],
return: [n]
# Macro syntax
match([{n}])
|> return([n])
Node and relationship representation
Seraph try to be as close to Cypher syntax as possible.
Nodes are represented by {variable, schema, properties}
where:
- variable is a
string
, - schema is a
Seraph.Schema.Node
, - properties are a
map
All variants are valid depending on the context.
Note that primary label will be deducted from schema and additional labels should be added
as properties under the key :additionalLabels
Node examples:
# Fully fleshed node
{u, MyApp.User, %{firstName: "John", lastName: "Doe"}}
# Node with no / useless properties
{u, MyApp.User}
# Node with only properties
{u, %{firstName: "John"}}
# Node with additional labels
{u, MyApp.User, %{additionalLabels: ["New", "Premium"]}}
Relationships are represented by [start_node, [variable, schema, properties], end_node]
where:
- start_node is a valid node representation
- variable is a
string
, - schema is a
Seraph.Schema.Relationship
, - properties are a
map
- end_node is a valid node representation
All variants are valid depending on the context
Relationship examples:
# Fully flesh relationship
[{u, MyApp.User, %{firstName: "John"}}, [rel, MyApp.Wrote, %{nb_edits: 5}], {p, MyApp.Post}]
# Relatinship without properties
[{u, MyApp.User}, [rel, MyApp.Wrote], {p, MyApp.Post}]
# Relatinship without variable
[{u, MyApp.User}, [MyApp.Wrote], {p, MyApp.Post}]
About literals and interpolation
The following literals are allowe in queries:
- Integers
- Floats
- Strings
- Boolean
- Lists
For the other types or dynamic values, you can interpolate them using ^
:
first_name = "John"
match([{u, MyApp.User}])
|> where([u.firstName == ^first_name])
Keyword order and entry points
In Cypher, keyword can be used in any order but only some can start a query. The same applies for Seraph queries. The entry point keywords / macros are:
match
create
merge
Note that because of this versability, it is possible to write invalid queries, a databse error will then be raised.
About operators and functions
Each Keyword / macro has a specific set ef availabe operators and functions. Please see the keyword / macro documentation for the aviable operators and functions.
About nil
In Neo4j, NULL
doesn't exists. This means that you can't have a null property and that setting a property to null will remove it.
Also, it is preferred to us is_nil
in where clause instead of using %{property: nil}
Link to this section Summary
Functions
Create a CREATE
clause from a list of nodes and/or relationships.
Create a DELETE
clause from list of variables.
Create a LIMIT
clause from value.
Create a MATCH
clause from a list of nodes and / or relationships.
Create a MERGE
clause from a node or relationship.
Create a ON CREATE SET
clause from a list of expression.
Create a ON MATCH SET
clause from a list of expression.
Create a ORDER BY
clause from a list of orders.
Create a REMOVE
clause from a list of properties and / or labels.
Create a RETURN
clause from a list of variables and / or properties and / or functions.
Create a SET
clause from a list of expressions.
Create a SKIP
clause from value.
Create a WHERE
clause from a boolean expression.
Link to this section Types
operation()
Specs
operation() :: :match | :where | :return
Specs
Link to this section Functions
Create a CREATE
clause from a list of nodes and/or relationships.
Cypher keyword:
CREATE
Entry point: yes
Expects: a list of nodes and / or relationships
Invalid data:
- Empty node: {},
- Empty relationship: [{}, [], {}]
- Node without schema: {u, %{prop1: value}} , {u}
Examples
# Creating a node (keyword syntax) create [{u, MyApp.User, %{uid: 1, firstName: "John"}}], return: [u] # Creating a node (macro syntax) create([{u, MyApp.User, %{uid: 1, firstName: "John"}}]) |> return([u]) # Creating a relationship (keyword syntax) create [ [ {u, MyApp.User, %{uid: 1}}, [rel, MyApp.Wrote, %{nb_edit: 5}], {p, MyApp.Post, %{uid: 2}} ] ], return: [rel] # Creating a relationship with a previous MATCH (keyword syntax) match [ {u, MyApp.User, %{uid: 1}}, {p, MyApp.Post, %{uid: 2}} ], create: [[{u}, [rel, MyApp.Wrote, %{nb_edit: 5}], {p}]], return: [rel] # Creating a relationship (macro syntax) create([ [ {u, MyApp.User, %{uid: 1}}, [rel, MyApp.Wrote, %{nb_edit: 5}], {p, MyApp.Post, %{uid: 2}} ] ]) |> return([rel])
Create a DELETE
clause from list of variables.
- Cypher keyword:
DELETE
- Entry point: no
- Expects: a list of variables.
Examples
# Keyword syntax
match [{u, MyApp.User, %{uid: 5}}],
delete: [u]
# Macro syntax
match([{u, MyApp.User, %{uid: 5}}])
|> delete([u])
Create a LIMIT
clause from value.
- Cypher keyword:
LIMIT
- Entry point: no
- Expects: a value.
Examples
# Keyword syntax
match [{u, MyApp.User}],
return: [u.firstName, u.lastName],
limit: 2
# Maccro syntax
match([{u, MyApp.User}])
|> return([u.firstName, u.lastName])
|> limit(2)
Create a MATCH
clause from a list of nodes and / or relationships.
- Cypher keyword:
MATCH
- Entry point: yes
- Expects: a list of nodes and / or relationships
- Invalid data:
- Empty node: {},
- Empty relationship: [{}, [], {}]
Examples
# Keyword syntax
match [
{u, User},
{p, Post},
[{u}, [rel, Wrote], {p}]
]
# Macro syntax
match([
{u, User},
{p, Post},
[{u}, [rel, Wrote], {p}]
])
Create a MERGE
clause from a node or relationship.
- Cypher keyword:
MERGE
- Entry point: yes
- Expects: a node or a relationship
- Invalid data:
- Empty node: {},
- Empty relationship: [{}, [], {}]
- Relationship without schema: [{u}, [rel], {p}]
Examples
# Merging a node (keyword syntax)
merge [{u, MyApp.User, %{uid: 1, firstName: "John"}}],
return: [u]
# Merging a node (macro syntax)
merge([{u, MyApp.User, %{uid: 1, firstName: "John"}}])
|> return([u])
# Merging a relationship (keyword syntax)
merge [
[
{u, MyApp.User, %{uid: 1}},
[rel, MyApp.Wrote, %{nb_edit: 5}],
{p, MyApp.Post, %{uid: 2}}
]
],
return: [rel]
# Merging a relationship with a previous MATCH (keyword syntax)
match [
{u, MyApp.User, %{uid: 1}},
{p, MyApp.Post, %{uid: 2}}
],
merge: [[{u}, [rel, MyApp.Wrote, %{nb_edit: 5}], {p}]],
return: [rel]
# Merging a relationship (macro syntax)
merge([
[
{u, MyApp.User, %{uid: 1}},
[rel, MyApp.Wrote, %{nb_edit: 5}],
{p, MyApp.Post, %{uid: 2}}
]
])
|> return([rel])
Create a ON CREATE SET
clause from a list of expression.
Require a MERGE
See set/2
for usage details.
Create a ON MATCH SET
clause from a list of expression.
Require a MERGE
.
See set/2
for usage details.
Create a ORDER BY
clause from a list of orders.
- Cypher keyword:
ORDER_BY
- Entry point: no
- Expects: a list of orders.
Default order is ascending (ASC)
Examples
# with default order (keyword syntax)
match [{u, MyApp.User}],
return: [u.firstName, u.lastName],
order_by: [u.firstName]
# with specific order (keyword syntax)
match [{u, MyApp.User}],
return: [u.firstName, u.lastName],
order_by: [desc: u.firstName]
# Macro syntax
match([{u, MyApp.User}])
|> return([u.firstName, u.lastName])
|> order_by([u.firstName])
Create a REMOVE
clause from a list of properties and / or labels.
- Cypher keyword:
REMOVE
- Entry point: no
- Expects: a list of properties and / or labels.
Examples
# Remove property (Keyword syntax)
match [{u, MyApp.User, %{uid: 1}}],
remove: [u.firstName],
return: [u]
# Remove label (Keyword syntax)
match [{u, MyApp.User, %{uid: 1}}],
remove: [{u, OldLabel}],
return: [u]
# Remove multiple labels (Keyword syntax)
match [{u, MyApp.User, %{uid: 1}}],
remove: [{u, [OldLabel1, OldLabel2]}],
return: [u]
# Remove property (Macro syntax)
match([{u, MyApp.User, %{uid: 1}}])
|> remove([u.firstName])
|> return([u])
Create a RETURN
clause from a list of variables and / or properties and / or functions.
- Cypher keyword:
RETURN
- Entry point: no
- Expects: a list of variables and / or properties and / or functions.
Note that functions and bare value must be aliased.
Note that distinct
has two usages:
At a general level, meaning
RETURN DISTINCT n, n.prop, ...
.In this case, all result fields should be arguments of the
distinct
like this:return: [distinct(n, n.prop, ....)]
.With aggregate function as other function:
count(distinct(u))
Available functions
min
max
count
avg
sum
st_dev
percentile_disc
distinct
collect
size
id
labels
type
start_node
end_node
Examples
# return matched data and properties
match [{u, MyApp.User, %{uid: 1}, {p, MyApp.Post}],
return: [u.firstName, p]
# aliased return
match [{u, MyApp.User}],
return: [names: u.firstName, bare_value: 5]
# distinct return
match [{u, MyApp.User}],
return: [distinct(u.firstName, u.lastName)]
# return function result
match [{u, MyApp.User, %{uid: 1}, {p, MyApp.Post}],
return: [nb_post: count(distinct(p))]
# Macro syntax
match([{u, MyApp.User, %{uid: 1}, {p, MyApp.Post}])
|> return([nb_post: count(distinct(p))])
Create a SET
clause from a list of expressions.
- Cypher keyword:
SET
- Entry point: no
- Expects: a list of expressions.
Valid operators
+
-
*
/
Valid functions
collect
id
labels
type
size
Examples
# with match (Keyword syntax)
match [{u, Myapp.User, %{uid: 1}}],
set: [u.firstName = "OtherName"]
match [{p, MyApp.Post}],
set: [p.viewCount = viewCount + 1]
match [
{p, MyApp.Post, %{uid: 45}},
{u, MyApp.User},
[{u}, [rel, MyApp.Read], {p}]
],
set: [p.viewCount = size(collect(u.uid))]
# with create (Keyword syntax)
create [{u, Myapp.User, %{uid: 99}}],
set: [u.firstName = "Collin", lastName = "Chou"]
# Set label (Keyword syntax)
match [{u, Myapp.User, %{uid: 1}}],
set: [{u, NewAdditionalLabel}]
# Set multiple label (Keyword syntax)
match [{u, Myapp.User, %{uid: 1}}],
set: [{u, [NewAdditionalLabel1, NewAdditionalLabel2]}]
# Macro syntax
match([{u, Myapp.User, %{uid: 1}}])
|> set([u.firstName = "OtherName"])
Create a SKIP
clause from value.
- Cypher keyword:
SKIP
- Entry point: no
- Expects: a value.
Examples
# Keyword syntax
match [{u, MyApp.User}],
return: [u.firstName, u.lastName],
skip: 2
# Maccro syntax
match([{u, MyApp.User}])
|> return([u.firstName, u.lastName])
|> skip(2)
Create a WHERE
clause from a boolean expression.
- Cypher keyword:
WHERE
- Entry point: no
- Expects: a boolean expression
Valid operators
and
(infix)or
(infix)xor
in
(infix)==
(infix)<>
(infix)>
(infix)>=
(infix)<
(infix)<=
(infix)is_nil
not
exists
starts_with
ends_with
contains
=~
Examples
# Keyword syntax
match [{u, MyApp.User}],
where: exists(u.lastName) and start_with(u.firstName, "J"),
return: [u.firstName]
# Macro syntax
match([{u, MyApp.User}])
|> where(exists(u.lastName) and start_with(u.firstName, "J"))
|> return([u.firstName])