using set clause in spring cypher query - neo4j

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(*)

Related

Neo4j new cypher format of relationship pattern

The relationship pattern in queries is changing, but the documentation is lacking. I get a "pending depreciation" message when writing this query:
match path = (p:Person)-[r:father|mother*0..5]->(a:Person)
return path limit 25
How do I write this to confirm to the new requirements?
It needs to be something like this but with some portion of the father|mother*0..5 moved into the relationships(path)
match path = (p:Person)-[r:father|mother*0..5]->(a:Person)
with *, relationships(path) as r
return path limit 25
That query runs okay but the error message persists.
What is the proper new format?
I assume Neo4j is complaining about the r . Can you try this:
match path = (p:Person)-[:father|mother*0..5]->(a:Person)
with *, relationships(path) as r
return path limit 25
The more complex case i would suggest to split the match
match path1= (p:Person{RN:5242})-[:father|mother*0..15]->(mrca:Person),
path2= (mrca)<-[:father|mother*0..15]-(b:Person{RN:1}) return length(path1), length(path2)

Neo4j Cypher and query construction based on condition

I have a following Cypher query:
MATCH (d:Decision)<-[:DEFINED_BY]-(ch:Characteristic)
WHERE d.id = {ownerDecisionId} and ch.lowerName = LOWER({name})
OPTIONAL MATCH (ch)-[rcho:CONTAINS]->(cho:CharacteristicOption)
RETURN ch, rcho, cho
Sometimes I don't need the following part of the query:
OPTIONAL MATCH (ch)-[rcho:CONTAINS]->(cho:CharacteristicOption)
Right now I'm going to introduce a new method with a different query for this purpose but would like to ask - is it a preferred approach in order to achieve this or there is another way in Cypher..for example I can introduce some new boolean variable and based on its value I can add a condition in order to return (or no) the following information: OPTIONAL MATCH (ch)-[rcho:CONTAINS]->(cho:CharacteristicOption)
The following query may do what you want without needing to use APOC. It assumes that executeOptionalMatch is a boolean parameter that indicates whether the OPTIONAL MATCH should be executed.
MATCH (d:Decision)<-[:DEFINED_BY]-(ch:Characteristic)
WHERE d.id = {ownerDecisionId} and ch.lowerName = LOWER({name})
OPTIONAL MATCH (ch)-[rcho:CONTAINS]->(cho:CharacteristicOption)
WHERE {executeOptionalMatch}
RETURN ch, rcho, cho
You can get the PROFILE of the query to see if the OPTIONAL MATCH does any significant work before its WHERE is executed. The profile I get in my version of neo4j shows that the WHERE filtering is done before the OPTIONAL MATCH does any real work.
Try installing APOC procedures and using apoc.when.
Considering these parameters:
:params {ownerDecisionId:10, name:'Jon',executeOptionalMatch:true}
You can run a query like this:
MATCH (d:Decision)<-[:DEFINED_BY]-(ch:Characteristic)
WHERE d.id = {ownerDecisionId} and ch.lowerName = LOWER({name})
CALL apoc.when({executeOptionalMatch}, 'OPTIONAL MATCH (ch)-[rcho:CONTAINS]->(cho:CharacteristicOption) RETURN rcho, cho', '', {ch:ch}) YIELD value
RETURN ch, value.rcho, value.cho
The OPTIONAL MATCH will be executed only when ownerDecisionId = true.
Note: remember to install APOC procedures according the version of Neo4j you are using. Take a look in the Version Compatibility Matrix.

Multiple match with where clause in Neo4j Cypher gives error "Cannot match on a pattern containing only already bound identifiers"

We are using neo4j-community-2.1.2. Right now we have only 3 nodes Of Job label in the database And we do Schema indexing on all fields that are used in this query . Total DB hits approx 40
Query is ->
PROFILE match (job1:Job) where (job1.jobType="Adhoc" or job1.jobType="Virtual") AND (job1.mode="Free" or job1.mode="Paid") with collect(job1) as jobs1
match (job2:Job)-[REQUIRED_SKILL]-(skill:Skill) where skill.name="Neo4j" and (job2 in jobs1) with collect(job2) as jobs2
match (job3:Job)-[REQUIRED_SKILL]-(skill:Skill) where skill.name="Java" and (job3 IN jobs2) with collect(job3) as jobs3 return jobs3
So we try to do something like that
match (job1:Job) where (job1.jobType="Adhoc" or job1.jobType="Virtual")
match (job1) where (job1.mode="Free" or job1.mode="Paid") with collect(job1) as jobs1 return jobs1
Because result of first match goes to next match . So that in next filter there is only need to filter less number of nodes But we get this exception
Cannot match on a pattern containing only already bound identifiers (line 2, column 1)
"match (job1) where (job1.mode="Free" or job1.mode="Paid") with collect(job1) as jobs1 return jobs1"
Optimize this Query
You cannot match job1 twice, once it is matched you can use the same instance again (using WITH), or in this case, you can filter on both conditions using AND. Also your query would be simpler by replacing OR with IN inclusion test, like this:
match (job1:Job)
where job1.jobType in ["Adhoc", "Virtual"]
and job1.mode in ["Free", "Paid"]
return collect(job1) as jobs1

Neo4J visit inner circle nodes only once

I have a Cypher query that returns closed circle results like
a-b-t-y-a
b-t-y-w-b
and so on ...
From time to time I get results like
a-b-c-b-e-f-a
c-e-r-e-f-g-c
c-e-r-c-d-a-c
that I do not need
In this two results I have b-in first and e in second visited twice , and c is
shown also not only at the start and at the end as it should be but in the middle also .
.
How to avoid getting results where I get same nodes in inner part of results or getting the start and end node inside also .The same node at the start and at the end of result is fine .
My current cypher query is :
start n=node(*) match p=n-[r:OWES*1..200]->n
where HAS(n.taxnumber)
return extract(s in `relationships(p) : s.amount), extract(t in nodes(p) : ID(t)), length(p);
I am getting all nodes that have taxnumber property and connected with relation OWES , all
up to level of 200 .
If you can't use CASE you could try this. I tested it on a 1.8.3 server and it runs ok. I was not able to get it working with reduce. I got several different unexpected errors, including 'unclosed parenthesis' and type comparison problems, this was the only query that I got to work. I also ran it on a 2.0 server and it finished in ~39s what Michael's query with case and reduce did in ~23s on a mockup data set.
START n=node(*)
MATCH p=n-[r:OWES*1..200]->n
WHERE HAS(n.taxnumber) AND
ALL(x IN tail(nodes(p)) WHERE SINGLE(y IN tail(nodes(p)) WHERE x=y))
RETURN EXTRACT(s IN relationships(p) : s.amount), EXTRACT(t IN nodes(p) : ID(t)), length(p)
Can't you check for non-duplicates in the path?
Right now cypher misses a uniq function that would make this simple, here is a workaround.
This is for neo4j 2.0, as 1.9 doesn't have case when there it might be more involved, probably using filter
start n=node(*)
match p=n-[r:OWES*1..200]->n
where HAS(n.taxnumber) AND
reduce(a=tail(nodes(p)), x in tail(nodes(p)) |
case when a IS NOT null OR x in tail(a) then null else tail(a) end) IS NOT NULL
return extract(s in relationships(p) | s.amount), extract(t in nodes(p) | ID(t)), length(p);
for 1.9 you might use an expression like this to find duplicates:
WITH [1,2,3] AS coll
reduce(a=false, x IN coll : a OR length(filter(y IN coll : x = y))> 1)
It works like this:
uses tail(nodes(path)) b/c you have the same start and end node which would always be a duplicate
it reduces over all elements of the collection and when it doesn't find the element again in the rest of the collection it returns the rest of the collection and repeats
otherwise it returns null and shortcuts

Cypher UNION query

I have the simple following graph:
http://console.neo4j.org/?id=v0cvwn
And I wonder why the following query:
START n=node(2)
match n-[:KNOWS]-node
return node.name as name
UNION
START n=node(2)
match n-[:ACTS_IN]-node
return node.name as name
throws an exception:
java.lang.AssertionError: assertion failed: Can't profile the same pipe twice
at scala.Predef$.assert(Predef.scala:179)
at org.neo4j.cypher.internal.profiler.Profiler.decorate(Profiler.scala:47)
at org.neo4j.cypher.internal.pipes.Pipe$class.createResults(Pipe.scala:35)
at org.neo4j.cypher.internal.pipes.NullPipe$.createResults(Pipe.scala:47)
at org.neo4j.cypher.internal.pipes.PipeWithSource.createResults(Pipe.scala:61)
at org.neo4j.cypher.internal.pipes.PipeWithSource.createResults(Pipe.scala:61)
at org.neo4j.cypher.internal.pipes.PipeWithSource.createResults(Pipe.scala:61)
at org.neo4j.cypher.internal.pipes.UnionIterator.loadNextIterator$1(UnionIterator.scala:60)
at org.neo4j.cypher.internal.pipes.UnionIterator.step$1(UnionIterator.scala:68)
at org.neo4j.cypher.internal.pipes.UnionIterator.stepIfNeccessary(UnionIterato
Couple of questions regarding UNION:
Is it possible to perform another final match clause on all the data which was accumulate in the result set as a result from the UNION in previous sub-queries?
Is it possible to perform an order by on that data?
Thanks.
According to these github comments, UNION is only support in version 2.0 or higher.
https://github.com/neo4j/neo4j/issues/125

Resources