neo4j Cypher - Match query pulling data no within set parameters

Viewed 17

Outline

I have a fairly basic match query that I want to get me results where the score field value is equal to or greater than the parameter. (10 in the below)

The Code

    MATCH (u:data)
    WHERE  u.score >= "10"
    RETURN id(u) AS id, u.score AS score
    LIMIT 10

Output

Currently I receive the following back

╒══════╤══════════════╕
│"id"  │"score"       │
╞══════╪══════════════╡
│906674│"860"         │
├──────┼──────────────┤
│906676│"1000"        │
├──────┼──────────────┤
│906677│"860"         │
├──────┼──────────────┤
│906879│"860"         │
├──────┼──────────────┤
│906882│"260"         │
├──────┼──────────────┤
│906888│"360"         │
├──────┼──────────────┤
│906989│"2100"        │
├──────┼──────────────┤
│907065│"1160"        │
├──────┼──────────────┤
│907107│"260"         │
├──────┼──────────────┤
│907152│"5"           │
└──────┴──────────────┘

As you can see, the last row has a score of 5 which is obviously not >= 10

Things I've tried

WHERE u.score >= 10 returns 0 rows

WHERE u.score >= '10' returns error

Thank you in advance for the help!!

1 Answers

Looks like you're storing numerical information as text - at which point the > and < comparison operators don't do what you think they do. Neo4j also won't do a type conversion for you - which is why when you try comparing to the number 10 rather than the string 10 you get no results at all (it just rejects all nodes because the datatype doesn't match what you're asking for).

For example:

WITH "5" as a, "10" as b
RETURN a > b

╒═══════╕
│"a > b"│
╞═══════╡
│true   │
└───────┘

As I understand it, Cypher'll do a character-by-character comparison when you ask it 'which string is bigger?'. So in your case, it'll look at 5 and 10 and say

Is the first character of the string '5' greater than the first character of the string '10'? Well in ASCII 5 > 1, so yes - return true

You either need to store numerical information as actual numbers in the node properties (at which point comparisons will work as you expect), or convert the node property to a number before doing the comparison. The second option may be a little slower, because the conversion has to happen on each node and you can't add a useful index to help out.

Still, given:

CREATE (a: Node { prop: "5" }), (b: Node { prop: "10" })

Then

MATCH (n:Node) WHERE n.prop >= 10
RETURN n

returns no results as you are seeing. But:

MATCH (n:Node) WHERE toInteger(n.prop) >= 10
RETURN n

Returns the node you're after.

As mentioned though, I'd strongly recommend updating your nodes to store the score property as a number instead of a string if it's genuinely numerical information.

Related