Reputation: 9291
I'd like to ensure I do not create multiple nodes with my neo4j database. I see here that this is the preferred method (even after reviewing this page), but I do not understand what the code is really doing in that example. Can someone possibly elaborate for the layman/noob?
Literal code is:
Create a Cypher execution engine and a unique constraint.
try ( Transaction tx = graphdb.beginTx() )
{
graphdb.schema()
.constraintFor( DynamicLabel.label( "User" ) )
.assertPropertyIsUnique( "name" )
.create();
tx.success();
}
return new ExecutionEngine( graphdb() );
Use MERGE to create a unique node.
Node result = null;
ResourceIterator<Node> resultIterator = null;
try ( Transaction tx = graphDb.beginTx() )
{
String queryString = "MERGE (n:User {name: {name}}) RETURN n";
Map<String, Object> parameters = new HashMap<>();
parameters.put( "name", username );
resultIterator = engine.execute( queryString, parameters ).columnAs( "n" );
result = resultIterator.next();
tx.success();
return result;
}
Upvotes: 4
Views: 6526
Reputation: 3308
The code appears to be creating a constraint with Cypher where the user and name must be unique, correct?
The code to create the constraint in this example is managed in the Java API for Neo4j. Labels group nodes together, and any node can have multiple labels. Refer here to learn more about labels:
http://docs.neo4j.org/chunked/milestone/graphdb-neo4j-labels.html
In this case, User
is a label that is assigned to a set of nodes within the graph. When we create a unique constraint, we tell Neo4j to assert a uniqueness constraint on a property within an arbitrary label.
That's managed in this statement:
graphdb.schema()
.constraintFor( DynamicLabel.label( "User" ) )
.assertPropertyIsUnique( "name" )
.create();
tx.success();
To do this in Cypher, it looks like this:
CREATE CONSTRAINT ON (user:User) ASSERT user.name IS UNIQUE
Refer here to learn more about Neo4j 2.0's optional schema:
http://docs.neo4j.org/chunked/milestone/query-constraints.html
If so, why are they storing things in a hash?
In the second chunk of code, which I've copied here for easy reference:
Node result = null;
ResourceIterator<Node> resultIterator = null;
try ( Transaction tx = graphDb.beginTx() )
{
String queryString = "MERGE (n:User {name: {name}}) RETURN n";
Map<String, Object> parameters = new HashMap<>();
parameters.put( "name", username );
resultIterator = engine.execute( queryString, parameters ).columnAs( "n" );
result = resultIterator.next();
tx.success();
return result;
}
We are wrapping a managed call within a transactional context. On the 4th line, we are creating our query string which is: MERGE (n:User {name: {name}}) RETURN n
, which means we want to MATCH
or CREATE
a user with an arbitrary name. The name is provided as the parameter {name}
which is supplied within the hash map named parameters
on the following line. The hash map is acting as a simple key/value list for our parameters where the key must match the provided parameter in the Cypher query, in this case {name}
.
resultIterator = engine.execute( queryString, parameters ).columnAs( "n" );
The transaction is then executed by supplying the query string, containing the Cypher statement with a declared parameter placeholder, and also the parameter map containing the key/value list.
If the insertion to the hash fails (not unique), then the try fails? If that is so, why even buid the constraint?
Since the MERGE
clause gets or creates (create happens if the record does not exist), a uniqueness constraint cannot be triggered within this context. If you were to try to use the CREATE
statement to create a node with a duplicate name
property, then the transaction would fail. The same is true if you attempted to SET
a name property on another node with a duplicate name
property within the set of nodes with the User
label.
Upvotes: 6