Subgraph constraint in neo4j - neo4j

Is it possible to add constraints on subgraphs? I have a tree type structure of items belonging to a category:
(cat:Category)<-[:OF_TYPE]-(item:Item {name:'foo'})
I want the name of each item that shares the same category to be unique, but item nodes of a different category should be able to have the same name. Can this be enforced with constraints?

Unfortunately currently there is no such functionality available in Neo4j.
You can only create contraints for whole database.
Alternatives:
Extension
You can create unmanaged extension that will register TransactionEventHandler. This one will be responsible for checking your specific domain constraints and reject invalid transactions.
Domain
You can alter your domain to make this available. For example - add DogCategoryItem label to each item under "dog" category. And then add separate constraint to DogCategoryItem only.
Note: I am not sure is it good or bad idead to have a lot of constraints in database (but my guess - nothing terrible should happen).

As FylmTM mentioned, this is not possible out of the box. However you can achieve this easily by having a compound property being a concatenation of the Category name and the Item name.
For example you can add a reference property on the Item node which should be unique for category name + item name concatenation
CREATE CONSTRAINT ON (i:Item) ASSERT i.reference IS UNIQUE
When you create an Item, you need to create this reference property value. As you will match anyway the Category node for creating the relationship, this is not a big deal :
MATCH (c:Category {name:"Category1"})
CREATE (i:Item {name:"Item1"})
SET i.reference = c.name + i.name
MERGE (i)-[:OF_TYPE]->(c)
If you try to create another Item with the same name in the same category, it will fails due to the Unique Constraint

Related

Create search index from a property list

I am building a database of genes in neo4j, with the main gene name as each node's unique identifier. However, each gene can go by other names, and i want those names to be searchable in the database as well.
I saw there might be a way to do this by indexing the alternate names to relate to the primary name, but not sure how to go about this. The two options i have seen are:
create new :Alias nodes for each alternate gene name, relate them to the primary node, then index that relationship.
Add an array of the alternate names as a property of the primary node, and index it that way.
Is there a correct method for doing this? Thanks

Core Data Unique constraint except for the default value

I have an entity called "Person". it has an attribute "id" with a default value = 0. I have set a constraint in "Person" to have only unique Ids. I am loading a list of Persons from the server and storing them locally using core data. The Person ids should be unique, but when I create multiple persons locally I want the uniqueness of id to be ignored if it has the default value 0.
I just want the uniqueness constraint to work on every id different then 0, how can I do this?
thanks,
Core Data's uniqueness constraints are just that-- they require uniqueness, without exceptions. Your situation of wanting "unique except for one value that can be duplicated" isn't directly supported by Core Data. You'd have to maintain that in your own code somehow. That probably means implementing your own update-or-insert logic to check whether an ID exists. That would be something like,
Do a fetch with the specific ID.
If you find an object update it.
If you don't find an object, create a new one.
Before constraints where add to core-data the only way to insure uniqueness is to do a fetch and then if there are no results create the object. It is not that difficult to do. Enforce uniqueness in you code and use whatever custom logic you need. Try to organize you code so that there are only one or two ways to create a person so the logic is easier to handle.

Create unique relationship based on relationship attribute

Just like we can create a unique constraint on a "Node" attribute, can i create a unique constraint on a "Relationship" attribute. In my system every relationship has a unique "name" attribute, i want to enforce it in neo4j.
Thank you
Utpal
Sorry, there is no support for unique constraints on relationships in neo4j 3.0.x, and nothing in the 3.1 beta documentation. Relationships can have existence constraints (for neo4j enterprise), but no unique constraints.
The best you can do is ensure you're always using MERGE when creating your relationships and that the name attribute is present for that MERGE.

Neo4J - Prevent duplicated relationship types with identical meaning

Consider Person nodes and Item nodes.
What is the best way to prevent having both 'Purchased' type relationships and 'Bought' type relationships in the graph that have the same meaning, but are simply named differently?
E.g. if we end up with our graph in a state like:
(Alice) -[Bought] -> (Pickles)
(Bob) -[Purchased]-> (Pickles)
and I want to know everyone who has bought a jar of pickles. Clearly someone made a mistake when creating one of these relationships. How do I prevent that class of mistake?
Limit the relationships a user can create to a specific set of names, and don't allow any other relationship names.

Why entity cannot have uniqueness constraints with to-one mandatory inverse relationship?

Why entity cannot have uniqueness constraints with to-one mandatory inverse relationship?
Having two entities:
Person
property: name
relationship: department (to-one, non-optional)
Department
property: title (unique constraint)
relationship: person (to-many, optional)
Model won't compile in iOS 9, XCode 7.0.1 with misconfigured entity error:
Misconfigured Entity: Entity Department cannot have uniqueness
constraints and to-one mandatory inverse relationship
Person.department
Update:
Question is still relevant in XCode 8.3.1.
Short answer:
The underlying problem is most likely caused by the sqlite standard. I'm not sure about that. How ever, it's very likely that it is because of the limitations of sqlite. I found some posts on the internet, where people had issues with multiple constraints on one table and thats most likely the reason why the two-table workaround works.
Long answer:
It's pretty late, but I hope it helps anyway.
This occurs when your Entity has an unique constraint and a mandatory relation. I guess it's because of the added unique constraint behaviors in iOS 9.0. However you can solve this in two ways:
You remove the unique constraint or make the relation optional. You could handle an optional relation in code. But it won't be a nice solution.
OR
You can use a workaround. You can have both. You can create a super class having a unique constraint. However this won't work without problems, too.
Let's you have three entities. A, B and C.
A is your super class and B is a sub class of A and C is a sub class of A, too. A has an unique constraint on it's property primaryKey. When saving instances of B and C, you can not have a B and C with the same primaryKey. Because CoreData will manage both as A.
You could change A to have two Properties:
int: originalPrimaryKey (NO unique constraint)
string: primaryKey (unique constraint)
You can now map your primaryKeys to originalPrimaryKey and when setting the originalPrimaryKey you could set the string primaryKey property to CLASS_NAME.{originalPrimaryKey}. This would allow you to have the behavior, you would expect. But you have to add a workaround for primaryKeys.
If you are trying to add constraints with existing entity with records ,
The solution is
1. delete all records from existing entity
2. delete existing relationships with the entity .
3. Regenerate the +CoreDataClass and +CoreDataProperties agin.
Make your relationship properties "optional". That fixed this problem in my case.

Resources