问题
excluse if this is a duplicate, although I did not find the answer so far.
I have an application that creates nodes and relationships via cypher statement against the REST-API. I create relationships with the below code:
public URI createRelationship(GraphNodeTypes sourceType, URI sourceNode,
GraphNodeTypes targetType, URI targetNode,
GraphRelationshipTypes relationshipType, String[] jsonAttributes) {
URI relationShipLocation = null;
String cypherArt = getNodeIdFromLocation(sourceNode)+"-[:"+relationshipType+"]->"+getNodeIdFromLocation(targetNode);
logger.info("creating relationship ({}:{}) -[:{}]-> ({}:{})",
sourceType,
getNodeIdFromLocation(sourceNode),
relationshipType,
targetType,
getNodeIdFromLocation(targetNode));
try {
URI finalUrl = new URI( sourceNode.toString() + "/relationships" );
String cypherStatement = generateJsonRelationship( targetNode,
relationshipType,
jsonAttributes );
logger.trace("sending CREATE RELATIONSHIP cypher as {} to endpoint {}", cypherStatement, finalUrl);
WebResource resource = Client.create().resource( finalUrl );
ClientResponse response = resource
.accept( MediaType.APPLICATION_JSON )
.type( MediaType.APPLICATION_JSON )
.entity( cypherStatement )
.post( ClientResponse.class );
String responseEntity = response.getEntity(String.class).toString();
int responseStatus = response.getStatus();
logger.trace("POST to {} returned status code {}, returned data: {}",
finalUrl, responseStatus,
responseEntity);
// first check if the http code was ok
HttpStatusCodes httpStatusCodes = HttpStatusCodes.getHttpStatusCode(responseStatus);
if (!httpStatusCodes.isOk()){
if (httpStatusCodes == HttpStatusCodes.FORBIDDEN){
logger.error(HttpErrorMessages.getHttpErrorText(httpStatusCodes.getErrorCode()));
} else {
logger.error("Error {} sending data to {}: {} ", response.getStatus(), finalUrl, HttpErrorMessages.getHttpErrorText(httpStatusCodes.getErrorCode()));
}
} else {
JSONParser reponseParser = new JSONParser();
Object responseObj = reponseParser.parse(responseEntity);
JSONObject jsonResponseObj = responseObj instanceof JSONObject ?(JSONObject) responseObj : null;
if(jsonResponseObj == null)
throw new ParseException(0, "returned json object is null");
//logger.trace("returned response object is {}", jsonResponseObj.toString());
try {
relationShipLocation = new URI((String)((JSONObject)((JSONArray)((JSONObject)((JSONArray)((JSONObject)((JSONArray)jsonResponseObj.get("results")).get(0)).get("data")).get(0)).get("rest")).get(0)).get("self"));
} catch (Exception e) {
logger.warn("CREATE RELATIONSHIP statement did not return a self object, returning null -- error was {}", e.getMessage());
relationShipLocation = null;
}
}
} catch (Exception e) {
logger.error("could not create relationship ");
}
return relationShipLocation;
}
private static String generateJsonRelationship( URI endNode,
GraphRelationshipTypes relationshipType, String[] jsonAttributes ) {
StringBuilder sb = new StringBuilder();
sb.append( "{ \"to\" : \"" );
sb.append( endNode.toString() );
sb.append( "\", " );
sb.append( "\"type\" : \"" );
sb.append( relationshipType.toString() );
if ( jsonAttributes == null || jsonAttributes.length < 1 ){
sb.append( "\"" );
} else {
sb.append( "\", \"data\" : " );
for ( int i = 0; i < jsonAttributes.length; i++ ) {
sb.append( jsonAttributes[i] );
if ( i < jsonAttributes.length - 1 ){
// Miss off the final comma
sb.append( ", " );
}
}
}
sb.append( " }" );
return sb.toString();
}
My problem is that I would like to check if a given relationship of given type already exists between two nodes PRIOR creating it.
Can someone tell me, how to query for a relationship???
With nodes I do a MATCH like this:
MATCH cypher {"statements": [ {"statement": "MATCH (p:SOCIALNETWORK {sn_id: 'TW'} ) RETURN p", "resultDataContents":["REST"]} ] }
against the endpoint
http://localhost:7474/db/data/transaction/<NUMBER>
How would I construct the statement to check for a relationship, say between node 6 and 5 or whatever?
Thanks in advance,
Chris
回答1:
You might want to consider doing this through cypher, and using the MERGE/ON CREATE/ON MATCH keywords.
For example, you could do something like this:
create (a:Person {name: "Bob"})-[:knows]->(b:Person {name: "Susan"});
MATCH (a:Person {name: "Bob"}), (b:Person {name: "Susan"})
MERGE (a)-[r:knows]->(b)
ON CREATE SET r.alreadyExisted=false
ON MATCH SET r.alreadyExisted=true
RETURN r.alreadyExisted;
This MATCH/MERGE
query that I provide here will return true or false, depending on whether the relationship already existed or not.
Also, FWIW it looks like the code you're using to accumulate JSON via StringBuilder
objects is likely to be ponderous and error prone. There are plenty of good libraries like Google GSON that will do JSON for you, so you can create JSON objects, arrays, primitives, and so on -- then let the library worry about serializing it properly to a string . This tends to make your code a lot cleaner, easier to maintain, and when you mess something up about your JSON formatting (we all do), it's way easier to find than when you accumulate strings like that.
回答2:
In Java
Relationship getRelationshipBetween(Node n1, Node n2) { // RelationshipType type, Direction direction
for (Relationship rel : n1.getRelationships()) { // n1.getRelationships(type,direction)
if (rel.getOtherNode(n1).equals(n2)) return rel;
}
return null;
}
来源:https://stackoverflow.com/questions/27233978/java-neo4j-check-if-a-relationship-exist