2016-08-07 7 views
0

В моем проекте SDN 4 У меня есть следующие entitites:Neo4j Cypher запрос с несколькими условиями

@NodeEntity 
public class Characteristic extends Authorable { 

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

    private String name; 

    private String description; 

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

} 

@NodeEntity 
public class Decision extends Commentable { 

    private final static String DEFINED_BY = "DEFINED_BY"; 

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

} 

@RelationshipEntity(type = "DECISION_CHARACTERISTIC") 
public class DecisionCharacteristic { 

    @GraphId 
    private Long id; 

    @StartNode 
    private Decision decision; 

    @EndNode 
    private Characteristic characteristic; 

    private Object value; 

} 

мне нужно, чтобы выбрать Decision узлов, которые соответствуют специфическим характеристикам.

Я создал следующий запрос: Cypher

MATCH (parentD)-[:CONTAINS]->(childD:Decision)-[ru:CREATED_BY]->(u:User) WHERE id(parentD) = {decisionId} MATCH (childD)-[rdc:DECISION_CHARACTERISTIC]->(characteristic:Characteristic) WHERE ((( id(characteristic) = 138 AND (rdc.value > 15000.32)) AND ( id(characteristic) = 138 AND (rdc.value < 50000.32))) AND ( id(characteristic) = 139 AND (rdc.value = 'Commercial'))) WITH childD, ru, u RETURN childD 

, но этот запрос работает неправильно. Мне нужно выбрать узлы решения, которые для характеристики с id=138 имеют value between 15000.32 and 50000.32 и для характеристики с id=139 имеет точный value = 'Commercial'.

Где я ошибаюсь в своем запросе и как его преобразовать, чтобы работать как ожидалось?

ОБНОВЛЕНО

У меня есть следующие узлы:

 DecisionCharacteristic neo4jPriceDecisionCharacteristic = new DecisionCharacteristic(neo4jDecision, priceCharacteristic, new Double(10000.32d)); 
     decisionCharacteristicRepository.save(neo4jPriceDecisionCharacteristic); 

     DecisionCharacteristic oraclePriceDecisionCharacteristic = new DecisionCharacteristic(oracleDecision, priceCharacteristic, new Double(35000.2d)); 
     decisionCharacteristicRepository.save(oraclePriceDecisionCharacteristic); 

     assertNotNull(neo4jPriceDecisionCharacteristic); 
     assertNotNull(neo4jPriceDecisionCharacteristic.getId()); 

     DecisionCharacteristic neo4jLicenseDecisionCharacteristic = new DecisionCharacteristic(neo4jDecision, licenseCharacteristic, "Commercial"); 
     decisionCharacteristicRepository.save(neo4jLicenseDecisionCharacteristic); 

     DecisionCharacteristic orientLicenseDecisionCharacteristic = new DecisionCharacteristic(orientDecision, licenseCharacteristic, "Free"); 
     decisionCharacteristicRepository.save(orientLicenseDecisionCharacteristic); 

     DecisionCharacteristic oracleLicenseDecisionCharacteristic = new DecisionCharacteristic(oracleDecision, licenseCharacteristic, "Commercial"); 
     decisionCharacteristicRepository.save(oracleLicenseDecisionCharacteristic); 

идентификаторы:

priceCharacteristic ID: 138 
licenseCharacteristic ID: 139 

Я пытаюсь получить Decision узлов с помощью следующего запроса:

MATCH (parentD)-[:CONTAINS]->(childD:Decision)-[ru:CREATED_BY]->(u:User) WHERE id(parentD) = {decisionId} MATCH (childD)-[rdc:DECISION_CHARACTERISTIC]->(characteristic:Characteristic) WHERE (id(characteristic) = 138 AND (id(characteristic) = 138 AND ( (rdc.value > 15000.32)) AND ( (rdc.value < 50000.32))) OR ( id(characteristic) = 139 AND (rdc.value = 'Commercial'))) RETURN childD 

Я ожидаю, что только oracleDecision узел соответствует этому условию, но он возвращает два узла:

Neo4j 
Oracle 

Где я ошибаюсь?

+0

Можете ли вы добавить к вашему описанию идентификаторы каждой из характеристик? Вы сопоставляете 138 или 139, но мы не можем сказать, к какому из них относятся. – InverseFalcon

+0

Я обновил свой вопрос: priceCharacteristic ID: 138 licenseCharacteristic ID: 139 – alexanoid

ответ

1

Основной недостаток в вашем запросе - использование AND для создания предложения where невозможного. Вы буквально просите его вернуть значения, где id - два разных числа, а где rdc.value - несколько значений одновременно ... невозможно. Вам нужно использовать ORs в правильных местах, чтобы вы могли сопоставлять один идентификатор или другой идентификатор. Кроме того, мы можем улучшить ограничение rdc.value.

MATCH (parentD)-[:CONTAINS]->(childD:Decision)-[ru:CREATED_BY]->(u:User) 
WHERE id(parentD) = {decisionId} 
MATCH (childD)-[rdc:DECISION_CHARACTERISTIC]->(characteristic:Characteristic) 
WHERE (id(characteristic) = 138 AND (15000.32 < rdc.value < 50000.32)) 
OR (id(characteristic) = 139 AND (rdc.value = 'Commercial')) 
WITH childD, ru, u 
RETURN childD 

Наконец, вам не нужно предложение WITH вообще, так как вы только возвращаете childD. Невероятно, если это потому, что вы забыли вернуть другие переменные в возврате, но если вы действительно возвращаете childD, то вы можете исключить предложение WITH, а также переменные ru и u в вашем первом совпадении строк. Если: Решения всегда создаются пользователями, то вы можете обрезать свой первый матч, избавившись от «- [ru: CREATED_BY] -> (u: User)». Это сделает ваш запрос выглядит следующим образом:

MATCH (parentD)-[:CONTAINS]->(childD:Decision) 
WHERE id(parentD) = {decisionId} 
MATCH (childD)-[rdc:DECISION_CHARACTERISTIC]->(characteristic:Characteristic) 
WHERE (id(characteristic) = 138 AND (15000.32 < rdc.value < 50000.32)) 
OR (id(characteristic) = 139 AND (rdc.value = 'Commercial')) 
RETURN childD 

EDIT

Ах, ладно, это не ясно из вашего запроса, который вы хотите, чтобы соответствовать по двум различным типам характеристик и установлены ограничения на обоих. В этом случае одного совпадения с характеристикой будет недостаточно. Вам нужно будет указать их отдельно.

MATCH (parentD)-[:CONTAINS]->(childD:Decision)-[:CREATED_BY]->(:User) 
WHERE id(parentD) = {decisionId} 
MATCH (childD)-[pdc:DECISION_CHARACTERISTIC]->(priceChar:Characteristic) 
WHERE (id(priceChar) = 138 AND (15000.32 < pdc.value < 50000.32)) 
MATCH (childD)-[ldc:DECISION_CHARACTERISTIC]->(licenseChar:Characteristic) 
WHERE (id(licenseChar) = 139 AND (ldc.value = 'Commercial')) 
RETURN childD 

Я должен спросить, вы действительно в порядке, моделируя свой график таким образом? У вас есть характерные узлы, но вы храните характерные данные по отношениям вместо самих узлов.Вы также используете один характерный узел, когда кажется очевидным, что у вас на самом деле есть отдельные типы, такие как PriceCharacteristic и LicenseCharacteristic и другие. У вас есть требования или веские причины для этого, или у вас есть свобода вносить изменения в то, как представлены ваши данные графа?

+0

Спасибо! Я обновил свой вопрос. Запрос по-прежнему не работает должным образом. – alexanoid

+0

Обновлен мой ответ для работы с вашими уточненными требованиями. – InverseFalcon

+0

Спасибо! Пожалуйста, см. Другой мой вопрос по причине этой схемы http://stackoverflow.com/questions/38639178/spring-data-neo4j-4-and-dynamic-product-properties – alexanoid

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