2016-08-07 18 views
0

In meinem SDN-4-Projekt habe ich eine folgende Entität:Neo4j Cypher Abfrage mit mehreren Bedingungen

@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; 

} 

Ich brauche einen Decision Knoten auszuwählen, die die spezifischen Eigenschaften entsprechen.

Ich habe folgende Cypher Abfrage erstellt:

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 

aber diese Abfrage funktioniert falsch. Ich muss einen Entscheidungsknoten auswählen, der für das Merkmal mit id=138 einen value between 15000.32 and 50000.32 hat und für das Merkmal mit genau value = 'Commercial' hat.

Wo liege ich falsch in meiner Abfrage und wie man es umwandelt, um wie erwartet zu arbeiten?

AKTUALISIERT

Ich habe einen folgenden Knoten:

 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); 

IDs:

priceCharacteristic ID: 138 
licenseCharacteristic ID: 139 

Ich versuche, einen Decision Knoten mit einer folgenden Abfrage zu erhalten:

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 

Ich gehe davon aus, dass nur oracleDecision Knoten diese Bedingung erfüllt, aber es gibt zwei Knoten:

Neo4j 
Oracle 

Wo bin ich falsch?

+0

Können Sie Ihrer Beschreibung die IDs der einzelnen Merkmale hinzufügen? Sie passen auf 138 oder 139, aber wir können nicht sagen, auf welche sie sich beziehen. – InverseFalcon

+0

Ich habe meine Frage aktualisiert: priceCharacteristic ID: 138 licenseCharacteristic ID: 139 – alexanoid

Antwort

1

Der Hauptfehler in Ihrer Abfrage besteht darin, ANDs zu verwenden, um eine unmögliche where-Klausel zu erstellen. Sie bitten ihn buchstäblich, Werte zurückzugeben, bei denen die ID zwei verschiedene Zahlen ist und der rdc.value gleichzeitig mehrere Werte hat ... unmöglich. Sie müssen ORs stattdessen an den richtigen Stellen verwenden, damit Sie eine ID oder eine andere ID zuordnen können. Außerdem können wir die rdc.value-Einschränkung verbessern.

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 

Schließlich brauchen Sie die WITH-Klausel überhaupt nicht, da Sie nur childD zurückgeben. Ist das nicht sicher, weil Sie vergessen haben, die anderen Variablen in der Rückgabe zurückzugeben, aber wenn Sie wirklich nur childD zurückgeben, dann können Sie Ihre WITH-Klausel sowie die ru- und u-Variablen in Ihrer ersten Übereinstimmung eliminieren. Wenn: Entscheidungen immer von Benutzern erstellt werden, können Sie die erste Übereinstimmung abschneiden, indem Sie "- [ru: CREATED_BY] -> (u: User)" entfernen. Dies würde Ihre Abfrage wie aussehen:

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

Ah, okay, es war aus der Abfrage nicht klar, dass Sie auf zwei verschiedene Arten von Eigenschaften und Beschränkungen für beide übereinstimmen. In diesem Fall reicht eine einzige Übereinstimmung mit einem Merkmal nicht aus. Sie müssen sie separat angeben.

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 

Ich muss fragen, sind Sie wirklich in Ordnung mit der Modellierung Ihrer Grafik auf diese Weise? Sie haben Merkmalsknoten, aber Sie speichern charakteristische Daten zu Beziehungen anstelle der Knoten selbst.Sie verwenden auch einen einzelnen Merkmalsknoten, wenn klar ist, dass Sie tatsächlich unterschiedliche Typen wie PriceCharacteristic und LicenseCharacteristic und andere haben. Haben Sie Anforderungen oder gute Gründe dafür oder haben Sie die Freiheit, Änderungen an der Darstellung Ihrer Diagrammdaten vorzunehmen?

+0

Vielen Dank! Ich habe meine Frage aktualisiert. Die Abfrage funktioniert immer noch nicht wie erwartet. – alexanoid

+0

Aktualisierte meine Antwort mit Ihren geklärten Anforderungen zu arbeiten. – InverseFalcon

+0

Danke! Bitte sehen Sie eine andere meine Frage aus einem Grund dieses Schemas http://stackoverflow.com/questions/38639178/spring-data-neo4j-4-and-dynamic-product-properties – alexanoid