WildBill
WildBill

Reputation: 9291

How to create unique node in neo4j?

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

Answers (1)

Kenny Bastani
Kenny Bastani

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

Related Questions