019
019

Reputation: 480

Neo4j: Invalid input '|': expected whitespace, comment, a relationship pattern

The following request

MATCH (n:artist) 
RETURN  [(:tag { _id : 'jazz' })-[:TAGS]->(n) AND (:tag { _id : 'pop' })-[:TAGS]->(n) | n._id] AS ids

returns the following error:

Invalid input '|': expected whitespace, comment, a relationship pattern, '.', node labels, '[', "=~", IN, STARTS, ENDS, CONTAINS, IS, '^', '*', '/', '%', '+', '-', '=', "<>", "!=", '<', '>', "<=", ">=", AND, XOR, OR, ',' or ']' (line 1, column 104 (offset: 103))

I have absolutely no clue on what's wrong, it seems like the problem is with the "AND" as this query works fine:

MATCH (n:artist) RETURN  [(:tag { _id : 'jazz' })-[:TAGS]->(n) | n._id] AS ids

Neo4j version: 3.3.4

Upvotes: 1

Views: 7769

Answers (2)

Nitin Kain
Nitin Kain

Reputation: 11

I have faced the similar issue in Neo4j Cypher Query while loading data from CSV file. In my case, there were near about 20 node properties. I was getting the error message

"Invalid input 'P': expected whitespace, comment, NodeLabel, MapLiteral, a parameter, a parameter (old syntax), ')' or a relationship pattern (line 2, column 20 (offset: 90))"

Query syntax was right.

Solution: It was working just moved long query to multiple lines by by just hitting enter button. An yes it worked for my case.

Upvotes: 1

Rebecca Nelson
Rebecca Nelson

Reputation: 1296

You cannot put AND in a pattern expression; it must go in a WHERE clause. You cannot put AND in the middle of two patterns. Usually, you would convert their constraints to WHERE syntax and put them in that clause; however, for your particular case, the query can be rewritten as a single pattern.

Try this:

MATCH (n:artist) 
RETURN  [(:tag { _id : 'jazz' })-[:TAGS]->(n)<-[:TAGS]-(:tag { _id : 'pop' }) | n._id] AS ids

And if you need to search for multiple tags, you can put additional tags in a WHERE clause directly after the main pattern in the list comprehension:

MATCH (n:artist) 
RETURN  [(:tag { _id : 'jazz' })-[:TAGS]->(n)<-[:TAGS]-(:tag { _id : 'pop' }) WHERE (:tag { _id : 'mytag1' })-[:TAGS]->(n) AND (:tag { _id : 'mytag1' })-[:TAGS]->(n) AND ... | n._id] AS ids

Finally, this solution, proposed by @Tezra, checks that each tag in the given list is searched for. It could be more performant for your queries; I'd recommend using PROFILE with each style to find the one that works best for you:

WITH ['jazz', 'pop', 'tag1', 'tag2', ...] AS tags MATCH (n:song) WHERE ALL(tag in tags WHERE (:tag {_id: tag})-[:TAGS]->(n)) RETURN n._id;

This will return a stream of IDs. To put all of the IDs in a single list returned as one value, replace the RETURN clause of the above statement with RETURN COLLECT(n._id) (suggested by @Emilien).

Upvotes: 2

Related Questions