Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
08-20-2019 03:32 PM
Neo4j 3.5.8
Neo4j and Cypher documentation everywhere for how to use parameters, and how they improve query performance. However, I've only found three well defined methods of passing parameters into a cypher query:
:param paramName: 'value';
... "parameters": { ... } ...
... "params": { ... } ...
However, none of these approaches address how to use parameters for efficient .cypher
scripts.
printf ":param test: 'tested'; \nCREATE (:Meta {name: \$test});\n" | cypher-shell -u neo4j -p neo4j
(note: that's not my actual user/pass)
Invalid input 'A': expected whitespace, comment, Statement or end of input (line 1, column 19 (offset: 18))
What am I missing?
Solved! Go to Solution.
08-20-2019 05:25 PM
With 3.5.8 running cypher-shell and then at the cypher-shell prompt entering :help
returns
$ cypher-shell
Connected to Neo4j 3.5.8 at bolt://localhost:7687.
Type :help for a list of available commands or :exit to exit the shell.
Note that Cypher queries must end with a semicolon.
neo4j> :help
Available commands:
:begin Open a transaction
:commit Commit the currently open transaction
:exit Exit the logger
:help Show this help message
:history Print a list of the last commands executed
:param Set the value of a query parameter
:params Prints all currently set query parameters and their values
:rollback Rollback the currently open transaction
For help on a specific command type:
:help command
For help on cypher please visit:
https://neo4j.com/docs/developer-manual/current/cypher/
neo4j> :help param
usage: :param name => value
Set the specified query parameter to the value given
neo4j>
as such the syntax for setting params in cypher-shell is
:param name=>value
the following should suffice
printf ":param test=>'tested' \nCREATE (:Meta {name: \$test});\n" | cypher-shell
08-20-2019 05:25 PM
With 3.5.8 running cypher-shell and then at the cypher-shell prompt entering :help
returns
$ cypher-shell
Connected to Neo4j 3.5.8 at bolt://localhost:7687.
Type :help for a list of available commands or :exit to exit the shell.
Note that Cypher queries must end with a semicolon.
neo4j> :help
Available commands:
:begin Open a transaction
:commit Commit the currently open transaction
:exit Exit the logger
:help Show this help message
:history Print a list of the last commands executed
:param Set the value of a query parameter
:params Prints all currently set query parameters and their values
:rollback Rollback the currently open transaction
For help on a specific command type:
:help command
For help on cypher please visit:
https://neo4j.com/docs/developer-manual/current/cypher/
neo4j> :help param
usage: :param name => value
Set the specified query parameter to the value given
neo4j>
as such the syntax for setting params in cypher-shell is
:param name=>value
the following should suffice
printf ":param test=>'tested' \nCREATE (:Meta {name: \$test});\n" | cypher-shell
08-21-2019 10:06 AM
Okay, so it turns out there were a few things contributing, but I'm still verifying more complex cypher scripts. These little quirks look like the only apply when piping into cypher-shell, and could probably use a PR, but knowing about them let me make some progress.
statement ; statement ;
statement ; \n statement ;
statement ;\n statement ;
statement \n statement
Newlines are the primary delimiter, and semicolons are needed to denote larger script blocks, not individual statements.
I guess I'm still learning, and Cypher is still maturing.
08-21-2019 11:22 AM
it is true that cypher statements are terminated by a ;
however :param
statements are not really true Cypher statements but rather convenience methods so as to set parameters.
Also, regarding your implementation of printf ........
this does work but you might want to make this more readable by putting the Cypher statements into a file and then catting the file into bin/cypher-shell
.
For example if the contents of example.cyp are
match (n) return count(n); match (n:Person) return count(n);
though stylistically and so as to be more readable this is probably better written as
match (n) return count(n);
match (n:Person) return count(n);
or even
match (n)
return count(n);
match (n:Person)
return count(n);
then to pass said file to bin/cypher-shell
run
cat example.cyp | bin/cypher-shell
08-21-2019 12:22 PM
That's exactly what I'm trying to do. Unfortunately, I keep finding a lot of undocumented nuances around how cypher-shell handles newlines, that differs greatly from other cypher implementations.
Perhaps I'm thinking about this the wrong way, and should simply store these values in temporary nodes, and delete those nodes at the end of the script?
Examples:
// works
:param test=>'test'
:param test2=>'test2'
//doesn't
:param test=>'test'; :param test2=>'test2';
// works
:param test=>'test'
RETURN $test
//doesn't
:param test=>'test'; RETURN $test;
//doesn't (space after semicolon, before newline
:param test=>'test';
RETURN $test
These minor examples are not really a big deal, but it made it much harder to figure out where and why other patterns weren't working either:
// works
:param testlist=>['test','list'];
RETURN $testlist;
// fails
:param testlist=>[
'test',
'list'
];
RETURN $testlist;
That last one is kind of a big deal, making clean code impossible for a list.
My main use for this is some of the more complex maps and args for APOC, but these can get fairly big, and are best not kept on one line.
08-21-2019 01:28 PM
Further experimentation has led me to the conclusion that the handling of the "convenience methods" is the real culprit here. Those things don't handle newlines well, but cypher-shell operates cleanly on everything else.
Is there any other way to get parameters into the cypher-shell for a script?
08-30-2019 09:59 AM
You're spot-on as always, but is there any other way to get parameters into the cypher-shell for a script?
02-08-2020 12:55 PM
I've run into the same thing with 3.5. There seems to be no way to pass a multi-line param?
:param testlist=>[
'test',
'list'
]
---
Invalid input 'R': expected whitespace, ...
:param testlist=>[\
---
Invalid input '\': expected whitespace, ...
I'm about to code passing large input data batches as a param list. I seem to have two choices:
#1 seems to be a better choice for me.
Is this possible in 4.0, by any chance?
02-10-2020 07:30 AM
There seems to be no way to pass a multi-line param?
Correct. But there might a workaround with apoc.
Drop a JSON file somewhere, and use apoc.load.json with a file:
path prefix.
Example
C:/path/myjson.json
{
"testlist": [
"test",
"list"
]
}
Cypher Command
CALL apoc.load.json("file:/C:/path/myjson.json") YIELD value
WITH value.testlist AS testlist
...
It's not as nice as a param, and doesn't come with the performance advantages, but at least you can have well-structured data.
02-11-2020 11:38 AM
This is great! Thanks.
All the sessions of the conference are now available online