I am using Spring Data with Neo4j, and I am creating POJOs for my schema. In this schema I have a node called Person, with the usual attributes, name, lastname, etc... I also have a relationship called DRIVES which establishes a relationship with another node called carModel:
(person)-[:DRIVES]->(carModel).
In my Person class, I have defined all the property fields and an annotation for the relationship and method as following:
#Relationship(type = "DRIVES", direction = Relationship.UNDIRECTED)
public CarModel carModel;
My question is, if in the CarModel class do I need to define the relationship as well ?
It is completely fine to create a model which declares the relationship only on one side.
The reasons for it might be
you simply don't want to refer from your CarModel class to Person
saves time during save operation on CarModel - SDN does not need to check if related Person has changed
UPDATE
The relationships stored in Neo4j are traversable in both directions, despite being defined only in Person class.
Using custom cypher queries you can query Person by CarModel and also CarModel by Person.
When using derived finders in SDN you can only use the direction which is defined in your class model.
Related
I have been using Core Data to model my database. I have 2 entities that are in many to many relationship. Each person can have many addresses, and on each address multiple persons can live.
Now i would like to add property to this relationship. For example one person - address will have label home, other person - address can will have label mama's place.
I can't add this property on address entity, because same address will have different labels for different persons.
Since relationships are modeled like NSSets, I don't see a way to do what I want.
Can this be somehow done?
It is not possible to add attributes to a many-many relationship directly. The Apple-recommended approach (see "Modelling a relationship based on its semantics" in the CoreData Programming Guide) is to replace the many-many relationship with an intermediate entity, to which you add the attributes. Each of your existing entities will have a one-many relationship with the new entity.
In your case, you might have something like this:
Person <--->> PersonAddressDetails <<---> Address
You can then add the label attribute to the PersonAddressDetails entity.
I'm new to Neo4J and I have a question about the most appropriate data model for a the problem domain described below.
Background
As I understand it, in Neo4J every relationship has a direction of sorts, outgoing, incoming or undirected. I read that a common mistake newbies make in "bi-directional" relationships is that they might model the relationship in both directions where in reality one undirected relationship would serve the purpose well. I also understand that irrespective of the direction it is possible at query time to ignore it and query based on either side of the relationship.
Problem Domain
This is a bit cliché, but stick with me, in a graph where "People" can connect with one another I felt tempted to model that as an undirected relationship. However, perhaps in my problem domain I want to store meta data on the relationship edge rather than at either of the People nodes. E.g. timestamp of when then connected or type of relationship (friend, family, employer etc...). Perhaps this is a "side effect" of using the spring-data-neo4j libraries but it seems that if I wish to data meta data on the edge rather than at the node I must create a class which is annotated as #RelationshipEntity rather than #NodeEntity. This necessitates a #StartNode and #EndNode which then seems to imply a direction to my otherwise undirected relationship...
Now, as it turns out this might not be a bad thing in my case because perhaps after all it turns out there is something useful about this additional directed context (e.g. perhaps I want to know who initiated the relationship so that the target node (person) must accept the invitation to be friends).
Now imagine that each person can place the "relationship" into a "group" like "friends, family, colleagues" etc I feel like I'd now need to actually have two distinct edges that point in either direction so that the meta data specific to the given direction has a natural place to reside. But this seems to have been described as a newbie anti-pattern.
Questions
I have two questions:
1) Should I use two separate distinct relationship edges that essentially point either way as a bi-directional relationship if I need to store meta data that is specific to the direction. e.g. Person A <--> Person B but person A placed Person B in the friends group whereas Person B placed A in the colleagues group.
2) Given the Java data model below, I am unclear what the direction attribute on the #Relationship annotation of Person should be. If I specify nothing it default to OUTGOING. But since it's a reflective relationship depending on which person instance you look at the relationship could be either outgoing or incoming, e.g. if person A adds person B, both are Person instances, but the direction is outgoing on the person A instance and incoming on the person B instance. Should the annotation be omitted altogether since I'm using a #RelationshipEntity?
Java Data Model
#NodeEntity
#EqualsAndHashCode(of = {"id"})
#NoArgsConstructor
public abstract class Person {
#GraphId
private Long id;
... other attributes
#Relationship(type = "CONNECTION_OF", direction = UNDIRECTED)
private Set<Connection> connections;
}
#Data
#RelationshipEntity(type = "CONNECTION_OF")
public class Connection {
#GraphId
private Long relationshipId;
... other meta-data
#StartNode
private Person from;
#EndNode
private Person to;
}
1) The rule of thumb that works well is to answer a question - if a relationship from A to B exists, can another relationship from B to A still be created, with different metadata? And can you delete one direction of the relationship independently of the other?
If the answer is yes they go for two directed relationships, otherwise stay with UNDIRECTED, and create initiatedBy=userId property or similar.
For your case where you put connections into groups - the thing is that you really categorize the people from another person's view, maybe it is a completely different fact independent of the CONNECTED_TO relationship?
You could e.g. create a group node and link that to owner and all people in the group, with following schema:
(:Person)-[:OWNS]-(:Group)-[:CATEGORIZED]-(:Person)
2) Keep the #Relationship(type = "CONNECTION_OF", direction = UNDIRECTED). For a given person X the connections Set is going to have elements that have from=X for outgoing edges mixed with elements that have to=X for incoming. All of these will be mixed in one collection.
I'm new to CoreData structure, I have two classes one is "Person.h" and another is "Education.h" which has one to many relations ship Person<--->> Education`.
Here's the attributes for each classes,
Person.h
personID (unique) Number
pName String
pAge Number
educations Set
here, p stands for person
Education.h
educationID (unique) Number
eName String
eState Number
eStarted String
eCompleted String
eCenterName String
eBy Person
here, e stands for education
Ok, now I want to fetch (all / some) education details for a Person. I've successfully inserted records in both the classes with proper inputs. How to get this done? Any suggestion? Please consider me to correcting, even if this flow would not clear to you (or its wrong).
Thanks,
Hagile
Normally you'd have a Core Data relationship on Person that points to the Education entity, configured as to-many. Then once you have an instance of Person, you just look up the value of that relationship like you'd look up the value of any property. You get back a collection of zero or more related Education instances, and you don't need to do an additional fetch.
Your eBy relationship on Education suggests that you're thinking of this as if you were working with SQL. With Core Data it's normal to have a to-many relationship defined on the entity that has the relationship (and indeed, eBy should really have an inverse relationship).
There are two entities in my app: Class and Student, they are many-to-many relationship, like following:
My problem is that in my app, there are two status of student in a class: pass and fail. I don't know how to model it to class or student. For example, should I make another Entity to express the status of a student? Or just adding a status attribute to Class entity?
Presumably you can't add an attribute to class because then if 20 students are taking the same class there'll be only one attribute between them?
You'll need to add a separate entity which has a to-one relationship with both a class and a student and which contains the status. And in reciprocal both student and class will have a to-many relationship with statuses.
EDIT: I guess an alternative solution would be to insert the status directly in between your existing relationship. So a class has a set of statuses, and each status has a student.
So relationships would be one to many from class to statuses and many to one from statuses to students. There'd be no explicit relationship between class and student.
I would suggest having a third entity which expresses the status for the student in a specific class. For example a Set of "classStatuses". Since you might need to store other information later, for example grades, credits, assistance records, etc etc.
The final scheme would be something like
Class - Student in a many to many relation.
Student - ClassStatus in a one to many. (Picture is as an array of the classes the student is taking with its respective status)
This way you can search for the students in a class, search for the classes a student is taking, check the status of the class.
Is it legitimate to create a one to one relationship between two entities when one is set to be abstract ?
An abstract entity is not meant to be instantiated. That's why you cannot create such a relationship. What you could do though is to create a relationship where the entity(s) are inheriting from an abstract entity.
From Apple's docs:
A relationship specifies the entity, or the parent entity, of the
objects at the destination. This can be the same as the entity at the
source (a reflexive relationship). Relationships do not have to be
homogeneous. If the Employee entity has two sub-entities, say Manager
and Flunky, then a given department's employees may be made up of
Employees (assuming Employee is not an abstract entity), Managers,
Flunkies, or any combination thereof.
EDIT:
Apparently you could create such a relationship (so that child entities would inherit the relationship as well)...
If you define an entity inheritance hierarchy (see “Entity
Inheritance”), when you specify a super-entity as the entity for a
fetch request, the request returns all matching instances of the
super-entity and of sub-entities. In some applications, you might
specify a super-entity as being abstract (see “Abstract Entities”). To
fetch matching instances of all concrete sub-entities of the abstract
entity, you set the entity for fetch specification to be the abstract
entity. In the case of the domain described in “Abstract Entities,” if
you specify a fetch request with the Graphic entity, the fetch returns
matching instances of Circle, TextArea, and Line.
See also this answer: Core Data: Abstract Entity in Fetch Request
yes. you can have a person who owns a "thing"...