neo4j: What is the syntax to set cypher query parameters in the browser interface? - neo4j

I am trying to run queries from the neo4j browser to reproduce results from my neo4j-javascript-driver client.
What is the syntax for defining query parameters in the neo4j b
I recently attended a neo4j training session in NYC where the trainer (David Fauth) did this, unfortunately, I did not take notes on it, since I figured that I could read-up on this online...but no success.

In neo4j-browser you need type for example:
:params {nodes: [{name: "John", age: 18}, {name: "Phill", age: 23}]}
Then you can use params as usual:
UNWIND {nodes} as node
MERGE (A:User {name: node.name, age: node.age})
RETURN A
For clear params in neo4j-browser type :params {}.
For additional help type :help params.

In Neo4j-3.3.4, the cypher likes this:
:param nodes: [{name: 'John', age: 18}, {name: 'Phill', age: 23}]
Neo4j Browser result:
here

In Neo4j Browser 3.5+ you can use the Cypher Shell parameter syntax, documented here: https://neo4j.com/docs/operations-manual/3.5/tools/cypher-shell/#cypher-shell-parameters
:param name => expression
The expression must be kept on a single line.
The expression could be a scalar or a list:
:param foo => ['a', 'b', 'c']
Maps can't be used directly with this syntax as of Neo4j 4.1. You can wrap them into a list:
:param foo => [{name: 'Alice', age: 38, address: {city: 'London', residential: true}}]
Or you can use :params:
:params {foo: {name: 'Alice', age: 38, address: {city: 'London', residential: true}}}

In Neo4j Browser 3.5+ you can use
:params param_name => 'param_value'

The basic cases:
Set singe variable value mytext="Hello": :param mytext => "Hello"
set dictionary values attr={"oid":1, "text":"Hello"}:
:param attr => ({oid: 1, text:"Hello"})
Cypher usage:
MATCH (x) WHERE x.a = $mytext RETURN x
set a value MATCH (x) WHERE x.a = $attr.oid SET x.b = $attr.text
set multiple values MATCH (x) WHERE ... SET x = $attr

Related

Neo4j/Cypher: How to exclude/include nodes with multiple properties?

I have a collection of nodes with multiple properties, for example:
(:Item {id: 1, type: 10})
(:Item {id: 2, type: 10})
(:Item {id: 1, type: 11})
(:Item {id: 1, type: 13})
(:Item {id: 2, type: 11})
In other examples, I can include nodes using a single value, using a query like this (with the IN clause):
MATCH (x:Item)
WHERE x.type IN [10,13]
RETURN x
Im trying to include/exclude nodes with certain properties, something like the next query:
MATCH (x:Item)
WHERE x IN [({id: 1, type: 10}), ({id: 2, type: 11})]
RETURN x
with the above query i don't get an error, but i don't get any results either. Could it be possible so that it includes or excludes certain nodes? In the above example could be more easy do 2-MATCHs for the 2 nodes, but in the real problem i want to include/exclude more than 10 nodes dynamically.
x in your example is much more that just a map with type and id, it is an identifier that represents the complete node.
If you rewrite x as a map of x.id and x.type then you can make that comparison.
MATCH (x:Item)
WHERE {id: x.id, type: x.type} IN [({id: 1, type: 10}), ({id: 2, type: 11})]
RETURN x

dustjs, duplication check while looping

While templating, what is the way to check if an array has same value?
I would like to skip if the array has duplicate value.
[
{name: 1},
{name: 3},
{name: 3},
{name: 4}
]
Sould out 1,3,4 on loop basically. Thanks
In general, Dust follows a philosophy that you should keep logic about your data out of the template. If you need to adjust your data before rendering it, you can write a helper function to pass the data through. Here's an example that uses Lodash's uniqBy to do this.
Context
{
yourArray: [{name: 1}, {name: 3}, {name: 3}, {name: 4}],
unique: function(chunk, context, bodies, {values, by}) {
const uniqueValues = _.uniqBy(values, by);
return chunk.section(uniqueValues, context, bodies);
}
}
Template
{#unique values=yourArray by="name"}
{name}{~n}
{/unique}
In this example, I've defined a context helper unique that accepts two parameters, an array to filter and a key to filter by.
I call _.uniqBy to filter the array, and then use chunk.section to render my block once for each value in uniqueValues.
Then, in the template, I call my context helper {#unique} and pass it the parameters.

neo4j pass parameter to variable length relationship

How do I use parameters with variable length relationships?
MATCH path=(:Person {id: {id}})=[:HAS_FRIEND*0..{num_friends}]->(:Person)
I'm trying to create a generic query so that I can pass a value 'num_friends' into the cypher query for various levels of relationships that I need.
I get an error so I'm wondering how something like this would be done?
Parameters can not be used as hops count.
But you can use path expander from apoc:
match (P:Person {id: {id}}) with P
call apoc.path.expand( P, 'HAS_FRIEND>', 'Person', 0, {num_friends}) yield path
return path
Adapted for comment:
match (P:Person {id: {id}}) with P
call apoc.path.expand( P, 'HAS_FRIEND>', 'Person', 0, {num_friends}) yield path
with path, last(nodes(path)) as lst where not (lst)-[:HAS_FRIEND]->(:Person)
return path

Neo4j console : Type mismatch: expected Collection<T> but was Node

I have a query that doesn't work. The error is:
Type mismatch: expected Collection but was Node coming from FOREACH..
Code:
MATCH (user:User {user_role: 'Customer'})
WITH user
OPTIONAL MATCH (user)-[hv:HAS_VAUCHER]->(v:Vaucher {status: 2})
WITH user, count(hv) as hv
WHERE hv = 0
WITH user
FOREACH (u IN user | CREATE (v:Vaucher {discount: 5, created_at: 1488531600, start_at: 1488531600, type: 'March', status: 2})<-[:HAS_VAUCHER]-(u))
I don't know where the error is.
While there are some improvements one could make to the query, here's a quick fix, dropping FOREACH since you don't have users in a collection, and you already have one user per row:
MATCH (user:User {user_role: 'Customer'})
WITH user
OPTIONAL MATCH (user)-[hv:HAS_VAUCHER]->(v:Vaucher {status: 2})
WITH user, count(hv) as hv
WHERE hv = 0
WITH user
CREATE (v:Vaucher {discount: 5, created_at: 1488531600, start_at: 1488531600, type: 'March', status: 2})<-[:HAS_VAUCHER]-(user)
I made a further research and the way to do it was to create a collection:
MATCH (user:User {user_role: 'Customer'})
WITH user
OPTIONAL MATCH (user)-[hv:HAS_VAUCHER]->(v:Vaucher {status: 2})
WITH user, count(hv) as hv
WHERE hv = 0
WITH user, COLLECT(user) AS users
FOREACH (u IN users | CREATE (v:Vaucher {discount: 5, created_at: 1488531600, start_at: 1488531600, type: 'March', status: 2})<-[:HAS_VAUCHER]-(u))
the "user" when returned returns N nodes (not 1) but when passed to FOREACH it maybe takes only the first node.
you can shorten the filtering part with a WHERE NOT clause and simplify query like this
MATCH (user:User {user_role: 'Customer'})
where not (user)-[:HAS_VAUCHER]->(:Vaucher {status: 2})
CREATE (v:Vaucher {discount: 5, created_at: 1488531600,
start_at: 1488531600, type: 'March', status: 2})<-[:HAS_VAUCHER]-(u)

Cypher zip collections

If I have two collections, how might I zip them together?
with [1,2,3] as nums, ['a', 'b', 'c'] as letters
... wat do? ...
return zipped // [{a: 1}, {b: 2}, {c: 3}]
It may not be possible to dynamically assign map keys (e.g., using the items in letters). But this query will return something similar to what you want (using collections instead of maps):
WITH [1,2,3] as nums, ['a', 'b', 'c'] as letters
RETURN EXTRACT(i IN RANGE(0, LENGTH(nums) - 1) | [letters[i], nums[i]]) AS result;
The result is:
[["a",1],["b",2],["c",3]]

Resources