cancel
Showing results for 
Search instead for 
Did you mean: 

Cypher parameters in CLI cypher-script

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:

  1. Neo4j Browser or cypher-shell:param paramName: 'value';
  2. HTTP-API 3.5 POST ... "parameters": { ... } ...
  3. Deprecated REST API POST ... "params": { ... } ...

However, none of these approaches address how to use parameters for efficient .cypher scripts.

Latest Attempt

printf ":param test: 'tested'; \nCREATE (:Meta {name: \$test});\n" | cypher-shell -u neo4j -p neo4j

(note: that's not my actual user/pass)

Result

Invalid input 'A': expected whitespace, comment, Statement or end of input (line 1, column 19 (offset: 18))

What am I missing?

1 ACCEPTED SOLUTION

dana_canzano
Neo4j
Neo4j

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

View solution in original post

9 REPLIES 9

dana_canzano
Neo4j
Neo4j

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

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.

newlines, semicolons, and statements

  • Statements must end with a newline.
  • There cannot be a space between the semicolon and the newline.
    • BAD: statement ; statement ;
    • BAD: statement ; \n statement ;
    • OK: statement ;\n statement ;
    • OK: statement \n statement

Takeaway

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.

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

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:

newlines over semicolon

// 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.

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?

You're spot-on as always, but is there any other way to get parameters into the cypher-shell for a script?

dkroot2
Node Link

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. Concatenate input data into a long string with no EOLs
  2. Concatenate input into the Cypher query itself

#1 seems to be a better choice for me.

Is this possible in 4.0, by any chance?

@dkroot2,

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.

dkroot2
Node Link

This is great! Thanks.

Nodes 2022
Nodes
NODES 2022, Neo4j Online Education Summit

On November 16 and 17 for 24 hours across all timezones, you’ll learn about best practices for beginners and experts alike.