Getting dynamic values from neo4j using Spring data - neo4j

public interface WayPointRepository extends GraphRepository, NamedIndexRepository, RelationshipOperationsRepository {
#Query( value = "start point=node:waypoints(\"name:{name1}\") return point", elementClass=WayPoint.class, type=QueryType.Cypher )
public List getWayPointByName(#Param("name1") String name);
}
i have a neo4j database with some points stored in it with index "waypoints", i want to get
some points dynamically after passing some points. for this i have created placeholder {name1},
but on calling the getWayPointByName with dynamic param gives me
nested exception is java.lang.RuntimeException: org.apache.lucene.queryParser.ParseException: Cannot parse 'name:{name1}': Encountered " "}" "} "" at line 1, column 11.
Was expecting one of:
"TO" ...
...
...
] with root cause
org.apache.lucene.queryParser.ParseException: Encountered " "}" "} "" at line 1, column 11.
Was expecting one of:
"TO" ...
...
...
at org.apache.lucene.queryParser.QueryParser.generateParseException(QueryParser.java:1818)
at org.apache.lucene.queryParser.QueryParser.jj_consume_token(QueryParser.java:1700)
at org.apache.lucene.queryParser.QueryParser.Term(QueryParser.java:1507)
at org.apache.lucene.queryParser.QueryParser.Clause(QueryParser.java:1309)
at org.apache.lucene.queryParser.QueryParser.Query(QueryParser.java:1237)
at org.apache.lucene.queryParser.QueryParser.TopLevelQuery(QueryParser.java:1226)
at org.apache.lucene.queryParser.QueryParser.parse(QueryParser.java:206)
exception

Use
start point=node:waypoints(name={name1}) return point
Within strings there is no parameter substitution happening.

Related

Neo4j Custom Procedures: How to pass query parameters?

I am trying to write a custom procedure for the Neo4J GraphDB in accordance to the documentation and the there referenced template. The procedure should ultimately generate a graph projection using the GDSL, for nodes with a certain label that is provided as a procedure parameter. For this it is, of course, necessary to pass the label to the query that is to be executed within the custom procedure. However, I cannot seem to find out how to pass parameters to a query string.
#Procedure(value = "custom.projectGraph")
#Description("Generates a projection of the graph.")
public Stream<ProRecord> projectGraph(#Name("graph") String graph) {
Map<String, Object> params = Map.of (
"graph", graph
);
return tx.execute("call gds.graph.project.cypher(\"$graph\", "
+ "\"MATCH (n:$graph) return id(n) as id\", "
+ "\"MATCH (src:$graph)-[]-(dst:$graph) "
+ "RETURN id(src) AS source, id(dst) AS target\") "
+ "YIELD graphName", params)
.stream()
.map(result -> (String) result.get("graphName"))
.map(ProRecord::new);
}
public static final class ProRecord {
public final String graphName;
public ProRecord(String graphName) {
this.graphName = graphName;
}
}
This code, unfortunately, does not work as intended, throwing the following exception:
Invalid input '$': expected an identifier
I did copy the syntax of prefixing placeholders with $-characters from other examples, as I could not find any hints on the passing of query parameters in the JavaDoc of the library. Is this even the correct documentation for custom neo4j procedures? Am I possibly using the wrong method here to issue my queries? It'd be very kind if someone could lead me into the right direction on that matter.
In general, when you use a string parameter the $param is automatically quoted, unlike the String.format for example.
Therefore there are 2 problems in your query:
\"$graph\" : in this case you are doubly quoting the parameter, try to write only $graph instead
Things like this n:$graph cannot be done unfortunately, the neo4j parameter handling is not able to recognize where to quote and where not, so you could use String.format or concat string with parameters (e.g. "MATCH (n:" + $graph + ") return id(n)...").
So, in short, this piece of code should work in your case:
return tx.execute("call gds.graph.project.cypher($graph, " +
"'MATCH (n:' + $graph + ') return id(n) as id', " +
"'MATCH (src:' + $graph + ')-[]-(dst:' + $graph + ') RETURN id(src) AS source, id(dst) AS target') YIELD graphName",
params)
.stream()
.map(result -> (String) result.get("graphName"))
.map(ProRecord::new);

How to bind `$jwt.sub` on Create to property using Neo4j and GraphQL?

I'm currently using neo4j and graphql with an Apollo server.
I have the following type:
type Person {
id: ID! #id
externalId: ID
name: String!
}
extend type Person
#auth(
rules: [
{ operations: [CREATE, UPDATE], bind: { externalId: "$jwt.sub" } }
]
)
And when I try to do the following mutation:
mutation Mutation($input: [PersonCreateInput!]!) {
createPeople(input: [
{
"name": "abc"
}
]) {
people {
name
}
}
}
I get a FORBIDDEN error from Neo4j.
I debugged a bit the code, and it looks like this is what's being transformed to:
CALL {\n' +
'CREATE (this0:Person)\n' +
'SET this0.id = randomUUID()\n' +
'SET this0.name = $this0_name\n' +
'WITH this0\n' +
'CALL apoc.util.validate(NOT(this0.externalId IS NOT NULL AND this0.externalId = $this0_auth_bind0_externalId), "#neo4j/graphql/FORBIDDEN", [0])\n' +
'RETURN this0\n' +
'}\n' +
'RETURN \n' +
'this0 { .name } AS this0',
so if I understand this correctly, if externalID is NULL AND externalID is different from my jwt sub value, then it will throw the exception.
And basically what I'm trying to achieve is:
When creating a person node, assign the externalID value to the value of the sub property of my JWT.
What am I doing wrong here?
I think the double negative is causing some confusion with the predicate. The exception will be thrown if this0.externalId is null OR if this0.externalId does not equal $this0_auth_bind0_externalId due to the AND statement and surrounding NOT.
Since you're creating this this0 above it will never have this0.externalId, so this predicate will always be true and the exception will always be thrown.
I'm not strong in GraphQL, but I would think your mutation needs to set the externalId.

Neo4J: List data type conversion

A string is stored in a node:
match (r:Reply)--(n:TRANS)
return split(toInteger(n.content), " ")
As you can imagine, the 'toInteger' method in the second line is incorrectly positioned - and returns exceptions.
Is there a method in Cypher where one can convert a list of Strings into a list of integers?
Here is an example of how to convert the numbers in a space-separated string to integers (in separate rows):
WITH '123 456 789' AS content
UNWIND SPLIT(content, " ") AS i
RETURN TOINTEGER(i) AS value;
And here is an example of how to get the integers in an array:
WITH '123 456 789' AS content
RETURN [i IN SPLIT(content, " ") | TOINTEGER(i)] AS values;

How can I rectify " Expected String instead saw "" " using jslint?

I've got a regular expression:
return (str+'').replace(/^(.)|\s(.)/g, function ( $1 ) { return $1.toUpperCase ( ); } );
I get following jslint error:
Expected String instead saw ""
How can I rectify this error?
It wants you to use
String(str)
isntead of
(str+'')
Invoking the String function as a "cast" is a slightly cleaner way to convert something to a string from some other type.
Use toString();
(new Date()).getTime()+""; instead (new Date()).getTime().toString();

Lua key name starts with digit in table statement

When key name starts with digit, in javascript we can define array-like object like this:
var table = {
'123.com': 'details'
'456.net': 'info'
}
But when I try these code in Lua5.1:
table = { '123.com' = 'info' }
It throws an error:
[string "local"]:1: '}' expected near '='
But these code are accepted in lua:
table = {}
table['123.com'] = 'info'
I wonder if it is a bug in Lua5.1. Or did I missed something?
When creating a Lua table using the literal table constructor, non-identifier table indices should be enclosed in square brackets. For example:
table = { ['123.com'] = 'info' }
(From: http://www.lua.org/pil/3.6.html)

Resources