问题
I am tryin to set two different relationship properties to a count, with a case construct depending on the value of another relationship property. There is a console at http://console.neo4j.org/?id=rt1ld5
the cnt column contains the number of times r.value occurs. The two first rows of the initial query in the console indicate that the term "Car" is linked to 1 document that is considered relevant, and to two documents that are considered not relevant.
I want to SET a property on the [:INTEREST] relation between (user) and (term) with two properties, indicating how many times an interest is linked to a document that is considered relevant or not. So for (John)-[r:INTEREST]->(Car) I want r.poscnt=1 and r.negcnt=2
I.m struggling with the CASE construct. I tried various ways, this was the closest I got.
MATCH (u:user)-[int:INTEREST]->(t:term)<-[:ISABOUT]-(d:doc)<- [r:RELEVANCE]-(u)
WITH int, t.name, r.value, count(*) AS cnt
CASE
WHEN r.value=1 THEN SET int.poscnt=cnt
WHEN r.value=-1 THEN SET int.negcnt=cnt
END
But it's returning an error
Error: Invalid input 'A': expected 'r/R' (line 3, column 2)
"CASE"
^
回答1:
This did it! Also see console at http://console.neo4j.org/?id=rq2i7j
MATCH (u:user)-[int:INTEREST]->(t:term)<-[:ISABOUT]-(d:doc)<-[r:RELEVANCE]-(u)
WITH int, t,
SUM(CASE WHEN r.value= 1 THEN 1 ELSE 0 END ) AS poscnt,
SUM(CASE WHEN r.value= -1 THEN 1 ELSE 0 END ) AS negcnt
SET int.pos=poscnt,int.neg=negcnt
RETURN t.name,int.pos,int.neg
回答2:
Is it important for you to keep positive and negative count separate? It seems you could have a score property summing positive and negative values.
MATCH (u:user)-[int:INTEREST]->()<-[:ISABOUT]-()<-[r:RELEVANCE]-(u)
SET int.score = SUM(r.value)
RETURN t.name, int.score
You already seem to have found a working solution but I'll add a note about CASE as I understand it. While CASE provides branching, I think it's correct to say that it is an expression and not a statement. It resembles a ternary operator more than a conditional statement.
As the expression
a > b ? x : y;
is resolved to a value, either x or y, that can be used in a statement, so also
CASE WHEN a > b THEN x ELSE y END
resolves to a value. You can then assign this value
result = CASE WHEN a > b THEN x ELSE y END
Your original query used the CASE expression like a conditional statement
CASE WHEN a > b THEN result = x ELSE result = y END
which resembles if-else
if a > b { result = x; } else { result = y; }
Someone may want to correct the terminology, the point is that in your working query you correctly let CASE resolve to a value to be used by SUM rather than put a conditional assignment inside CASE.
来源:https://stackoverflow.com/questions/22459893/set-in-combination-with-case-statement-in-cypher