2
votes

I'm using Spring data neo4j 2.1.0.BUILD-SNAPSHOT and Neo4j 1.6.1 server. I have a Friendship relationship between two User nodes, and I want to ensure that only one relationship will be created for every user1, user2 pair (the order doesn't count).

Common suggestion is to check at application level if a relationship already exists before creating another one, but I think that doesn't avoid concurrency problems: the constraint should be managed at the database level.

The best solution I can think of is to use the @Indexed annotation with unique property introduced in Neo4j 1.6 and create a unique constraint based on the user1 and user2 ids, something like

@Indexed(unique = true)
private String uniqueConstraint;
public String getUniqueConstraint(){
    if(user1.id > user2.id){
        return user1.id + "|" + user2.id;
    }
    return user2.id + "|" + user1.id;
}

BTW I know that the latest release of Spring data neo4j supports this check on nodes with Neo4jTemplate.getOrCreateNode(), but I'm not sure it works with Relationships. The rest API should be there though. Unique relationship

So I have two questions:

1 Is there any better alternative?

2 Should I be bothered by this concurrency problem, or it's very unlikely that something bad happens even in a high traffic site and the check at application level should be sufficient? I ask because it seems to me a very common problem, but there's little around about this with Neo4j. Maybe the embedded version suffers less from this.

Thanks

1

1 Answers

3
votes

The usual approach in SDN of having relationships between two nodes already ensures that there is only one relationship of one type between them (by checking upfront).

It doesn't yet leverage the uniqueness support in Neo4j for that.

And yes, with the REST-Server this approach might run into concurrency/racing conditions.

The embedded version supports locking (e.g. on one of the 2 nodes - or both) and then creating the relationship with that lock in place. So that there is no second thread doing the same thing at the same time.

It might be ok, if you do it optimistically. I.e. check after creation and delete afterwards. You can also leverage the REST-API directly to support that behaviour. We probably add support for that by SDN 2.1 could you raise an issue (linking to this post) at http://spring.neo4j.org/issues ?