2016-07-27 4 views
1

В моем проекте Spring Data Neo4j У меня есть следующие объекты:Neo4j Cypher запрос с нулевым или не нулевым значением

@NodeEntity 
public class Decision extends Commentable { 

    private final static String CONTAINS = "CONTAINS"; 
    private final static String DEFINED_BY = "DEFINED_BY"; 

    private String name; 

    @Relationship(type = DEFINED_BY, direction = Relationship.INCOMING) 
    private Set<CriterionGroup> criterionGroups = new HashSet<>(); 

    @Relationship(type = DEFINED_BY, direction = Relationship.INCOMING) 
    private Set<Criterion> criteria = new HashSet<>(); 

... 

} 

@NodeEntity 
public class Criterion extends Authorable { 

    private final static String CONTAINS = "CONTAINS"; 
    private final static String DEFINED_BY = "DEFINED_BY"; 

    private String name; 

    @Relationship(type = CONTAINS, direction = Relationship.INCOMING) 
    private CriterionGroup group; 

    @Relationship(type = DEFINED_BY, direction = Relationship.OUTGOING) 
    private Decision owner; 

... 

} 

@NodeEntity 
public class CriterionGroup extends Authorable { 

    private final static String DEFINED_BY = "DEFINED_BY"; 
    private final static String CONTAINS = "CONTAINS"; 

    private String name; 

    @Relationship(type = DEFINED_BY, direction = Relationship.OUTGOING) 
    private Decision owner; 

    @Relationship(type = CONTAINS, direction = Relationship.OUTGOING) 
    private Set<Criterion> criteria = new HashSet<>(); 

... 

} 

У меня есть следующий SDN метод репозитория:

@Query("MATCH (d:Decision)<-[:DEFINED_BY]-(c:Criterion) WHERE id(d) = {decisionId} and c.name = {name} RETURN c") 
Criterion findCriterionDefinedByDecisionByName(@Param("decisionId") Long decisionId, @Param("name") String name); 

На основе этого запроса Я могу получить Criterion, что принадлежит Decision и имеет определенное имя.

Критерий в моей доменной модели может (или не относится) к CriterionGroup.

Мне нужно расширить этот запрос, чтобы добавить еще одно условие для проверки CriterionGroup, связанного с этим критерием. Другими словами, мне нужно вернуть Criterion с определенным {name} для определенного {decisionId}, который принадлежит (или нет в случае нулевого значения) к предоставленному {criterionGroupId}. В случае {criterionGroupId} == null мне нужно найти Критерий, который не принадлежит ни одному CriterionGroup.

мне нужно что-то вроде этого:

@Query("MATCH (d:Decision)<-[:DEFINED_BY]-(c:Criterion)...????????...... WHERE id(d) = {decisionId} and c.name = {name} RETURN c") 
Criterion findCriterionDefinedByDecisionByName(@Param("decisionId") Long decisionId, @Param("name") String name, @Param("criterionGroupId") Long criterionGroupId); 

Пожалуйста, помогите мне написать этот запрос.

ответ

1

Это должно работать, и не должно быть слишком медленным либо, если у вас есть десятки тысяч CriterionGroups за Criterion:

MATCH (d:Decision)<-[:DEFINED_BY]-(c:Criterion) 
WHERE id(d) = {decisionId} 
    AND c.name = {name} 
OPTIONAL MATCH (c)<-[:CONTAINS]-(cg:CriterionGroup) 
WITH c, extract(g IN collect(cg) | id(g)) AS cgIds 
WHERE CASE 
     WHEN {criterionGroupId} IS NULL THEN size(cgIds) = 0 
     ELSE {criterionGroupId} IN cgIds 
     END 
RETURN c 

В качестве альтернативы, вы можете иметь 2 метода в вашем Repository, чтобы управлять каждый случай непосредственно , используя

MATCH (d:Decision)<-[:DEFINED_BY]-(c:Criterion) 
WHERE id(d) = {decisionId} 
    AND c.name = {name} 
    AND NOT (c)<-[:CONTAINS]-(:CriterionGroup) 
RETURN c 

когда criterionGroupId является нулевым, и

MATCH (d:Decision)<-[:DEFINED_BY]-(c:Criterion), 
     (c)<-[:CONTAINS]-(cg:CriterionGroup) 
WHERE id(d) = {decisionId} 
    AND c.name = {name} 
    AND id(cg) = {criterionGroupId} 
RETURN c 

в противном случае.

+0

Спасибо большое! У меня будет одна группа CriterionGroup (не тысячи!), Связанная с одним критерием (но у меня будут тысячи критериев, решений и CriterionGroup). Одна группа CriterionGroup может иметь несколько десятков Критерий. Таким образом, с точки зрения производительности безопасно использовать решение номер один с одним запросом? – alexanoid

+0

Вы пройдете _from_ «Criterion' _to_ 0 или 1« CriterionGroup », не должно быть проблем с производительностью с одним запросом. –

+0

Спасибо! Запрос работает отлично! – alexanoid

Смежные вопросы