问题
I have a following SDN 4 entities:
Decision
, Characteristic
and Value
:
@NodeEntity
public class Value extends Votable {
private final static String SET_FOR = "SET_FOR";
private final static String SET_ON = "SET_ON";
private final static String CONTAINS = "CONTAINS";
@Relationship(type = SET_FOR, direction = Relationship.OUTGOING)
private Decision decision;
@Relationship(type = SET_ON, direction = Relationship.OUTGOING)
private Characteristic characteristic;
@Index(unique = false)
private Object value;
...
}
I have created 3 Decicion
(Decicion1
, Decision2
, Decisison3
) nodes and 1 Characteristic
(Characteristic1
).
For Decicion1
, Decicion2
and Characteristic1
I have created a Double
Value
, for example:
Decision1 + Characteristic1 = Value(500d)
Decision2 + Characteristic1 = Value(1000d)
Decicion3 doesn't have any Value on Characteristic1
I need to create a query that will return all Decision
which have Value
in the defined range, for example 100 <= value <= 50000
Based on the example above this query should return Decision1
and Decicion2
only.
Right now I have a following query:
MATCH (parentD)-[:CONTAINS]->(childD:Decision)-[ru:CREATED_BY]->(u:User)
WHERE id(parentD) = {decisionId}
AND ALL(key IN keys({rangeFilters})
WHERE size(
[(childD)<-[:SET_FOR]-(filterValue)-[:SET_ON]->(filterCharacteristic) WHERE id(filterCharacteristic) = toInt(key) AND ({rangeFilters}[key])[0] <= filterValue.value <= ({rangeFilters}[key])[1] | 1]
) > 0)
RETURN ru, u, childD AS decision SKIP 0 LIMIT 100
where rangeFilters
is a Map<String, Double[]>
where key is a Characteristic
ID
and value new Double[] { new Double(100.d), new Double(50000d) }
But this query returns all 3 Decision
, even the Decision3
that don't have any values associated with Characteristic1
.
How to fix this query in order to return only Decisions
that match a condition ?
UPDATED
This is an example that highlights the issue: http://console.neo4j.org/?id=6bv9y5
UPDATED
I'm tried to apply solution described by Tezra
. This is my curent query:
MATCH (parentD)-[:CONTAINS]->(childD:Decision)-[ru:CREATED_BY]->(u:User)
WHERE id(parentD) = {decisionId}
MATCH (childD)<-[:SET_FOR]-(filterValue)-[:SET_ON]->(filterCharacteristic)
WHERE
ALL(key IN keys({equalFilters}) WHERE id(filterCharacteristic) = toInt(key) AND filterValue.value = ({equalFilters}[key]))
AND
ALL(key IN keys({rangeFilters}) WHERE id(filterCharacteristic) = toInt(key) AND ({rangeFilters}[key])[0] <= filterValue.value <= ({rangeFilters}[key])[1])
RETURN ru, u, childD AS decision SKIP 0 LIMIT 100
Unfortunately assertion in my tests fails on this query.
This query works fine only when I specify the single filter condition, for example:
ALL(key IN keys({equalFilters}) WHERE id(filterCharacteristic) = toInt(key) AND filterValue.value = ({equalFilters}[key]))
or
ALL(key IN keys({rangeFilters}) WHERE id(filterCharacteristic) = toInt(key) AND ({rangeFilters}[key])[0] <= filterValue.value <= ({rangeFilters}[key])[1])
but doesn't work when both of them are present. What am I doing wrong ?
回答1:
Based on the example data, you just need to link all the checks correctly. (the parent stuff isn't in the example, but I think it was just the key-range part messing you up)
WITH {c1:[100,50000]} AS rangeFilters
MATCH (childD:Decision)<--(fv:FilterValue)-->(c:FilterCharacteristic)
WHERE ALL(key IN keys(rangeFilters)
WHERE c.id=key AND rangeFilters[key][0] < fv.value < rangeFilters[key][1])
RETURN childD
Although you could also make FilterValue a relationship since relationships can have properties too.
UPDATE:
As for your problem with WHERE ALL( equals...) AND ALL(in_range...); That reads "Where all equal filters are true and all range filters are true". So I'm guessing that you actually want is any of them to be true which would be WHERE ANY (equals...) OR ANY(in_range) (available predicates), as it is impossible for filter.value to equal 7 and 9 at the same time.
Also, as a side note, don't use id() in your queries, as Neo4j reserves the right to change those as much or little as it likes. Set your own id fields, and use a UUID instead. A UUID is also much more reliable if you need to merge data sets.
来源:https://stackoverflow.com/questions/43855265/neo4j-cypher-node-filtering-by-pattern-comprehension