I am trying to creating user defined procedure.
i got the sample project from this github repository https://github.com/neo4j-examples/neo4j-procedure-template. i created the jar file and moved to /var/lib/neo4j/plugins
i am getting the unknown function error
If anyone knows about it help me please
also i restarted my neo4j also
neo4j> MATCH (p: Person) WHERE p.age = 36 RETURN org.neo4j.examples.join(collect(p.names));
Unknown function 'org.neo4j.examples.join' (line 1, column 44 (offset: 43))
"MATCH (p: Person) WHERE p.age = 36 RETURN org.neo4j.examples.join(collect(p.names));"
If you look at the comment on the java method for this function, you will see into the description annotation, that to call it you should do : example.join(...) and NOT org.neo4j.examples.join.
This function is under the java package example, and the name of the function is join, so it gives you example.join
You can define manually what is the way to call a function by adding a name attribut into the UserFunction annotation. Like this :
#UserFunction( "test.nodeList" )
public List<Object> nodeList()
{
Result result = db.execute( "MATCH (n) RETURN n LIMIT 1" );
Object node = result.next().get( "n" );
return Collections.singletonList( node );
}
And call it in cypher like this :
RETURN test.toSet(['a', 'b'])
Related
I have an edge with sevral properties. I would like to keep the edge but remove only the name property.
My java Cypher is this :
public static final String DELETE_EDGE_PROPERTY_QUERY = //
"MATCH ()-[r]->() where id(r) = {1} REMOVE r.{2} RETURN r"; //
It works on cypher console but doesn't work on jdbc.
I got this error :
processing failed; nested exception is org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [MATCH ()-[r]->() where id(r) = {1} REMOVE r.{2} RETURN r]; SQL state [null]; error code [0]; Some errors occurred :
[Neo.ClientError.Statement.SyntaxError]:Invalid input '{': expected an identifier, whitespace, a function name or a property key name (line 1, column 45 (offset: 44))
"MATCH ()-[r]->() where id(r) = {1} REMOVE r.{2} RETURN r"
`
Any suggestions?
Thanks
EDIT
I couldn't do with jdbc template.
so I have used String replacement:
Setting the property to NULL will delete the property
(http://www.baeldung.com/java-neo4j)
Solution :
Java :
String deleteQuery = String.format(DELETE_EDGE_PROPERTY_QUERY, property);
plantJdbcTemplate.update(deleteQuery, edgeId);
cypher :
public static final String DELETE_EDGE_PROPERTY_QUERY = //
"MATCH ()-[r]->() where id(r) = {1} SET r.%s = NULL RETURN r";
This not a neo4j-jdbc issue, it's related to the design of Neo4j about parameterized query.
On a query you can parameterized all data you want, except:
labels
relationship types
properties
If you want to do it in Cypher, there are a lot of helpers in the APOC plugin.
When I use the following query:
MATCH (emp:Employee)
WHERE emp.supervisor_id = 159
RETURN emp
I get a result as 4 employees/nodes with supervisor_id = 159
and for this query I also get a result which is 1 employee with employeeID = 159 :
MATCH (emp:Employee)
WHERE emp.employeeID = 159
RETURN emp
But when I use the = operator, it does return (no changes, no records).
MATCH (emp:Employee)
WHERE emp.employeeID = emp.supervisor_id
RETURN emp
I assume it's a logic mistake, but I just can't figure it out.
Any idea pls.
In your query you are searching a node with the label Employee that has its attribute employeeID equals to supervisor_id.
Or from what I understand, what you want is to search two differents nodes with the label Employee.
So your query should be this one :
MATCH (emp1:Employee), (emp2:Employee)
WHERE emp1.employeeID = emp2.supervisor_id
CREATE (emp1)-[:MANAGER_OF]->(emp2)
This query create a Cartesian product, so if you have a lot of Employee nodes, you should batch the creation of relationships with an APOC procedure (https://neo4j-contrib.github.io/neo4j-apoc-procedures/) like this :
CALL apoc.periodic.iterate(
"MATCH (emp1:Employee) RETURN emp1",
"MATCH (emp2:Employee) WHERE emp1.employeeID = emp2.supervisor_id CREATE (emp1)-[:MANAGER_OF]->(emp2)",
{batchSize:5000, parallel:true}
);
Cheers
I am trying to use the SUM function and store the result of it as a new property of the relationship. But it is not working.
The query I used is :
MATCH (a:Employee)-[r:CorporateMessage]->(b)
WHERE a.Eid = 6001 AND b.Eid IN [6002,6003,6004,6005,5001]
SET r.Internalsum = SUM(r.Count)
The error i got was:
Invalid use of aggregating function sum(...) in this context (line 1, column 124 (offset: 123)) "MATCH (a:Employee)-[r:CorporateMessage]->(b)WHERE a.Eid = 6001 AND b.Eid IN [6002,6003,6004,6005,5001] SET r.Internalsum = SUM(r.Count)"
Kindly explain what i am doing wrong.
Try it:
MATCH (a:Employee)-[r:CorporateMessage]->(b)
WHERE a.Eid = 6001 AND b.Eid IN [6002,6003,6004,6005,5001]
WITH r, SUM(r.count) as count
SET r.Internalsum = count
Always put aggregation functions in WITH or RETURN.
I have the following java code snippet that demonstrates the problem. The error I receive is also included below.
It correctly pulls the correct set, but I am having trouble printing.
I'm using the org.neo4j.graphdb.Node node. Is this the wrong class?
If not, how do I obtain the results movieid, avgrating and movie_title from the ExecutionEngine?
Java Code
GraphDatabaseService db = new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH);
ExecutionEngine engine = new ExecutionEngine(db);
String cypherQuery = "MATCH (n)-[r:RATES]->(m) \n"
+ "RETURN m.movieid as movieid, avg(toFloat(r.rating)) as avgrating, m.title as movie_title \n"
+ "ORDER BY avgrating DESC \n"
+ "LIMIT 20;";
ExecutionResult result = engine.execute(cypher);
for (Map<String, Object> row : result) {
Node x = (Node) row.get("movie_title");
for (String prop : x.getPropertyKeys()) {
System.out.println(prop + ": " + x.getProperty(prop));
}
}
Error
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to org.neo4j.graphdb.Node
at beans.RecommendationBean.queryMoviesWithCypher(RecommendationBean.java:194)
at beans.RecommendationBean.main(RecommendationBean.java:56)
Node x = (Node) row.get("movie_title");
...looks to be the culprit.
In your Cypher statement, you return m.title as movie_title, i.e. you're returning a node property (in this case, a string), and, in the offending line, you're trying to cast that string result as a Node.
If you want Cypher to return a series of nodes you can iterate through, try returning m (the whole node) instead of just individual properties and aggregates, e.g.
"...RETURN m AS movie;"
...
Node x = (Node) row.get("movie");
Etc.
Trying to execute the following cypher query (which executes ok from neoclipse)
START a=node(*) MATCH a-[:Knows]->p WHERE (p.Firstname! = "Steve" ) RETURN p
from neo4jclient with the following statement
protected void Populate()
{
var client = new GraphClient(new Uri("http://altdev:7474/db/data"));
client.Connect();
var query = client.Cypher
.Start(new RawCypherStartBit("all", "node(*)"))
.Match("all-[:Knows]->p")
.Where((Person p) => p.Firstname == "Steve")
.Return<Node<Person>>("Person");
var people = query.Results;
}
the client throws an exception, as follows
The query was: START all=node(*)
MATCH all-[:Knows]->p
WHERE (p.Firstname! = {p0})
RETURN Person
The response status was: 400 Bad Request
The response from Neo4j (which might include useful detail!) was: {
"message" : "Unknown identifier `Person`.",
"exception" : "SyntaxException",
"fullname" : "org.neo4j.cypher.SyntaxException",
"stacktrace" : [ "org.neo4j.cypher.internal.symbols.SymbolTable.evaluateType(SymbolTable.scala:59)", "org.neo4j.cypher.internal.commands.expressions.Identifier.evaluateType(Identifier.scala:47)", "org.neo4j.cypher.internal.commands.expressions.Expression.throwIfSymbolsMissing(Expression.scala:52)", "org.neo4j.cypher.internal.pipes.ColumnFilterPipe$$anonfun$throwIfSymbolsMissing$1.apply(ColumnFilterPipe.scala:61)", "org.neo4j.cypher.internal.pipes.ColumnFilterPipe$$anonfun$throwIfSymbolsMissing$1.apply(ColumnFilterPipe.scala:61)", "scala.collection.immutable.List.foreach(List.scala:309)", "org.neo4j.cypher.internal.pipes.ColumnFilterPipe.throwIfSymbolsMissing(ColumnFilterPipe.scala:61)", "org.neo4j.cypher.internal.pipes.PipeWithSource.<init>(Pipe.scala:63)", "org.neo4j.cypher.internal.pipes.ColumnFilterPipe.<init>(ColumnFilterPipe.scala:30)", "org.neo4j.cypher.internal.executionplan.builders.ColumnFilterBuilder.handleReturnClause(ColumnFilterBuilder.scala:60)", "org.neo4j.cypher.internal.executionplan.builders.ColumnFilterBuilder.apply(ColumnFilterBuilder.scala:38)", "org.neo4j.cypher.internal.executionplan.ExecutionPlanImpl.prepareExecutionPlan(ExecutionPlanImpl.scala:54)", "org.neo4j.cypher.internal.executionplan.ExecutionPlanImpl.<init>(ExecutionPlanImpl.scala:36)", "org.neo4j.cypher.ExecutionEngine$$anonfun$prepare$1.apply(ExecutionEngine.scala:80)", "org.neo4j.cypher.ExecutionEngine$$anonfun$prepare$1.apply(ExecutionEngine.scala:80)", "org.neo4j.cypher.internal.LRUCache.getOrElseUpdate(LRUCache.scala:37)", "org.neo4j.cypher.ExecutionEngine.prepare(ExecutionEngine.scala:80)", "org.neo4j.cypher.ExecutionEngine.execute(ExecutionEngine.scala:72)", "org.neo4j.cypher.ExecutionEngine.execute(ExecutionEngine.scala:76)", "org.neo4j.cypher.javacompat.ExecutionEngine.execute(ExecutionEngine.java:79)", "org.neo4j.server.rest.web.CypherService.cypher(CypherService.java:94)", "java.lang.reflect.Method.invoke(Method.java:616)", "org.neo4j.server.rest.security.SecurityFilter.doFilter(SecurityFilter.java:112)" ]
}
As you can see, essentially the queries are the same. And the nodes I'm trying to get are of _type "Person"
TIA
Marcelo
In your MATCH clause you use the identity p:
.Match("all-[:Knows]->p") // becomes MATCH all-[:Knows]->p
In your RETURN clause you change to using the identity Person:
.Return<Node<Person>>("Person"); // becomes RETURN person
You need to pick one and be consistent.
Integrating some other clean up too, your full query should be:
var query = client.Cypher
.Start(new { all = All.Nodes })
.Match("all-[:Knows]->p")
.Where((Person p) => p.Firstname == "Steve")
.Return<Person>("p");
It's down to the way you are creating the Cypher code, specifically what you are returning:
var query = client.Cypher
.Start(new RawCypherStartBit("all", "node(*)"))
.Match("all-[:Knows]->p")
.Where((Person p) => p.Firstname == "Steve")
.Return<Node<Person>>("p"); // <-- THIS LINE SHOULD SAY 'P' NOT 'Person'
The return statement requires the name to be the same as the node you have defined. So you use: all-[:knows]->p where you define p. Now you need to return it.
(Which is what Peter is saying in his answer :))
You are trying to return a Person node that is not assigned to anything in the query.