I'am trying to use cypher dsl to create a Statement which results in
merge(n:entity {name:'value'}
set n += {k1:'v1',k2:'v2'}
return n
I parsed it with the CypherParser and it is oke. I see that the set clause has a mutate operator which , i quess, handles the '+='. But when i try to create it with the cypher dsl api i can't find how to express the '+='
Without '+=' the cypher dsl is something like:
var node = Cypher.node("entity").withProperties("name", Cypher.literalOf("value"))
var expression = Cypher.mapOf("k1", Cypher.literalOf("v1"), "k2", Cypher.literalOf("v2")
var statement = Cypher.merge(node).set(expression).returning(node).build()
This will result in : merge(n:entity {name:'name'} set n = {k1:'v1',k2:'v2'} return n.
The name property is gone when executing this query.
How can i express the '+=' in cypher dsl?
thanks
Related
I want to test all nodes in the path from node a to node b (with only MATCH statement), where the depth is changing (could be any number). In the example below the depth is 2.
START a = node(86)
MATCH p0 = a-[*..2]-b
WHERE (b.attr = 'true') AND (a.attr = 'true')
RETURN p0
My question is how do I test the nodes between a and b for a certain attribute (attr = 'true'), using the MATCH statement, without knowing the depth required.
I find that using filter method I can filter out all the unwanted nodes.
like:
START a = node(86)
MATCH p0 = a-[*..2]-b
RETURN filter(x IN nodes(p0) WHERE x.attr = 'true')
But that is not what I need, I need to use MATCH.
Take a look at the Cypher refcard, specifically to the List Predicates section. The all() function should do the trick.
Something like:
START a=node(86)
MATCH p0=(a)-[*..2]-(b)
WHERE ALL(node in nodes(p0) WHERE node.attr = true)
RETURN p0
This will only match patterns where all the nodes in the pattern have that attribute as true.
For illustrating this issue, create thousand nodes labeled z having incrementing numeric attribute zid.
FOREACH (i IN range(1, 1000)| CREATE (z:z { zid: i }));
Now find a node using random zid value between 1 and 1000.
MATCH (n:z { zid: round(rand()*1000)})
RETURN n;
The above cypher returns inconsistent results, sometimes no nodes are returned, sometimes multiple nodes are returned.
Tweaking the cypher as follows yields consistent results.
WITH round(rand()*1000) AS x
MATCH (n:z { zid: x })
RETURN x, n;
What is wrong with the first cypher query ?
The reason why you are receiving inconsistent results with the first query has to do with how Neo4j evaluates Cypher queries. The function round(rand()*1000) is evaluated for each of the items within the label index for z when using WHERE or concise syntax. When you use the WITH clause, the function is evaluated once.
That being said, this looks like a bug that is specific to the rand() function.
I want to do something like this in cypher:
MATCH (n:node) WHERE n.ID = x //x is an integer value
FOREACH (num in n.IDs:
MATCH (p:node) WHERE p.ID = num
CREATE (n)-[:LINK]->(p) )
where num is an array of integer values referring to the IDs of nodes that need to be linked to the node matched in the first line.
When I run this query, I get the error: Invalid use of MATCH inside FOREACH.
I'm in the early stages of teaching myself both Cypher and Neo4j. How can I achieve my desired functionality here? Or am I barking up the wrong tree - am I failing to grasp something that makes it unnecessary for me to do so?
This is not allowed, instead use the top-level MATCH like http://gist.neo4j.org/?8332363
MATCH (n:node), (p:node)
WHERE n.ID = 1 AND p.ID in [2,3,4]
CREATE (n)-[:LINK]->(p)
please provide me some example to use set clause in cypher query using java.
i just want to update property of relationship object but it always fail.
if i am running query like
ExecutionResult executionResult = engine.execute("start n=node:Person(name=\"suresh\"),n2=node:Email(subject=\"Hi\") match (n)-[r]-(n2) return r ");
System.out.println(executionResult);
i am getting proper response like below
+-----------------------------------------------------------------------------------------------------------------------------+
| r |
+-----------------------------------------------------------------------------------------------------------------------------+
| :DynamicRelationshipType[Have][69] {accessed->true,__type__->"org.test.spring.neo.domain.EmailRelationShip",relation->"To"} |
+-----------------------------------------------------------------------------------------------------------------------------+
1 rows, 260 ms
but when i am trying to run query like
start n=node:Person(name=\"suresh\"),n2=node:Email(subject=\"Hi\") match (n)-[r]-(n2) CREATE SET r.accessed=true return r
it always fail
stack Trace
expected return clause
"start n=node:Person(name="suresh"),n2=node:Email(subject="Hi") match (n)-[r]-(n2) CREATE SET r.accessed=true return r "
^
at org.neo4j.cypher.internal.parser.v1_6.CypherParserImpl.parse(CypherParserImpl.scala:65)
at org.neo4j.cypher.CypherParser.parse(CypherParser.scala:42)
at org.neo4j.cypher.ExecutionEngine$$anonfun$prepare$1.apply(ExecutionEngine.scala:60)
at org.neo4j.cypher.ExecutionEngine$$anonfun$prepare$1.apply(ExecutionEngine.scala:60)
at org.neo4j.cypher.internal.LRUCache.getOrElseUpdate(LRUCache.scala:31)
at org.neo4j.cypher.ExecutionEngine.prepare(ExecutionEngine.scala:60)
at org.neo4j.cypher.ExecutionEngine.execute(ExecutionEngine.scala:54)
at org.neo4j.cypher.ExecutionEngine.execute(ExecutionEngine.scala:51)
at org.neo4j.cypher.javacompat.ExecutionEngine.execute(ExecutionEngine.java:63)
at org.test.spring.neo.controller.MediatorController.main(MediatorController.java:34)
i tried to execute like below also but this one is also failing
ExecutionResult executionResult = engine.execute("start n=node:Person(name=\"suresh\"),n2=node:Email(subject=\"Hi\") match (n)-[r]-(n2) SET r.accessed=false return r ");
i am referring http://docs.neo4j.org/refcard/1.9/ to create a read and write query
i am using sdn version 1.8.
Please Help
As the error message says: "expected return clause"
Neo4j 1.8 is more restricted than e.g. 2.0
e.g. something like this works:
start n=node:Person(name="abc"), n2=node:Email(subject="Hi")
match (n)-[r]-(n2)
set r.accessed=true
return count(*)
You should also always use parameters:
start n=node:Person(name={person}), n2=node:Email(subject={subject})
match (n)-[r]-(n2)
set r.accessed=true
return count(*)
Using the py2neo tutorial (http://book.py2neo.org/en/latest/cypher/):
from py2neo import neo4j, cypher
graph_db = neo4j.GraphDatabaseService()
query = "START a=node(1) RETURN a"
data, metadata = cypher.execute(graph_db, query)
a = data[0][0] # first row, first column
Trying to replicate this, I get:
>data[0][0]
Node('http://localhost:7474/db/data/node/1')
How do I get this to return the actual data, instead of the abstract information?
Your Cypher query returns a node (RETURN a) and so that's what's being passed back: a Node object. If it's the node's properties that you need, you can either then inspect the properties on that node with the get_properties method or return specific properties from the Cypher query instead (RETURN a.name).