Constraint Validation in Neo4j

Warm Greetings to All!

I am trying to create two different graphs in Neo4j belonging to 2 different domains, say, one for a Retail Store and other for a Bank.

There are many entities which are common across two domains like Customer etc but i would like to have different Nodes created for these common entities for each domain so as to have a separate set of nodes/relationships which can be easily queried later,independently.

However, since Neo4j doesn't provide any container/workspace(unlike Grakn or other Graph dbs ) to keep different domain graphs separated from each other in a single Neo4j instance, i am using multiple labels to differentiate the Nodes of two domains.

For instance, Cypher Syntax for Customer Node of Retail Store is -

      Create (:Customer :RetailStore :Tree {id: 'Customer'})  

and, Cypher Syntax for Customer of Bank is -

      Create (:Customer :Bank :Tree {id: 'Customer'})  

However, after creating one of the graph in Neo4j i am unable to create the other graph as Neo4j throws error
"Neo.ClientError.Schema.ConstraintValidationFailed: Node(324) already exists with label Tree and property id = 'Customer'

i need 'Tree' label so as to utilize Graph Traversal API while querying the domain graphs.

I also observed that if 'Tree' label is removed then i am able to create the two graphs in Neo4j. In fact, after removing 'Tree' i am able to create the same Node 'n' number of times without getting Constraint Validation error. from Neo4j. Please try below syntax, say for 10 times, we won't get any error.

Create (:Customer :RetailStore {id: 'Customer'})

Can you please throw some light on what is special about 'Tree' & 'id', and why Neo4j doesn't throw Constraint Validation error when we don't use 'Tree' as label and try to create same node 'n' number of times(as we expect, since a node with that name & property already exists). Thanks.

You have made a UNIQUE CONSTRAINT on :Tree(id), and you are trying to create two :Tree nodes with the same id.

You can see your constraints by running :schema in the browser.

In Neo4j 4.0 you can opt to keep workspaces separated in different databases (requires Enterprise license).

1 Like

Thanks @Thomas_Silkjaer for sharing the insights.

@Thomas_Silkjaer Is the neo4j driver could route the request by a tenant to the right DB?

Thomas gives a great answer. The only downside to multiple DBs, though, is that you cannot then query both graphs with one transaction unless you implement the Fabric add-on layer.

In your case, it doesn't seem like you care about querying both graphs at once, so multi-DB is the best bet. But just to mention for posterity...if you want to retain the easy ability to query both graphs together or separately, you'll need to work with labels a little bit more specifically and cleverly. You can't rely on simple label-stacking to differentiate the domains.

For example, to query all Customers at once, you'd want to keep the generic label Customer used by both graphs. But to store and query bank and retail customers separately, you'd want something like BankCustomer and RetailCustomer labels. And the unique constraints would apply to the more specific labels, not the generic one.

In similar situations, I added a property "customerType" to the Customer node and set the value as "Bank" or "Retail". Also create a unique constraint on id and customerType. The query:

MATCH (a:Customer) WHERE a.customerType = "Bank" (for Bank customer) or "Retail" for Retail customer. Try this.