Reputation: 247
I am trying to use Neo4J with Spring Data, but I am not sure if my design is correct (First time I use a graph database). The problem is that I don't know if I should model everything as a Node or just a simple attribute.
Example : (My biggest node)
@NodeEntity
public class User{
@Indexed(unique=true)
private String username;
@Indexed(unique=true)
private String email;
// Is a node ???
private Location location
private int areaRadius;
//No need to create a rich relationship
@RelatedTo(type=RelationshipTypes.LIKES, direction=Direction.OUTGOING)
@Fetch
private Set<Hobby> hobbies = new HashSet<Hobby>;
//No need to create a rich relationship
@RelatedTo(type=RelationshipTypes.HAS_CATEGORY, direction=Direction.OUTGOING, elementClass=Category.class)
@Fetch
private Set<Category> favCategories = new HashSet<Category>;
//Must create a rich relationship (Friendship.java)
@RelatedTo(type=RelationshipTypes.FRIEND_OF, direction=Direction.BOTH)
@Fetch
private Set<User> friends = new HashSet<User>;
//Rich relationship between Users (Friendship.java)
@RelatedToVia(type=RelationshipTypes.FRIEND_OF)
@Fetch
private Set<Friendship> friendships = new HashSet<Friendship>;
//Must create a rich relationship (UserEvent.java)
@RelatedTo(type=RelationshipTypes.GOING_TO, direction=Direction.OUTGOING)
@Fetch
private Set<Event> events = new HashSet<Event>;
//Rich relationship between Users (UserEvent.java)
@RelatedToVia(type=RelationshipTypes.GOING_TO)
@Fetch
private Set<UserEvent> userEvents = new HashSet<UserEvent>;
// Is a node ???
private Set<Status> statusList;
private URI profilePicture;
public User(){}
public User(String username, String email, Location location){
this.username = username;
this.email = email;
this.location = location;
}
public void addHobby(Hobby hobby){
this.hobbies.add(hobby);
}
public void sendFriendRequestTo(User user){
this.friendships.add(new Friendship(this, user, Friendship.REQUESTED);
}
public void addCategory(Category category){
this.favCategories.add(category);
}
public void addConfirmedEvent(Event event){
this.userEvents.add(new UserEvent(this, event, false));
}
public void addMaybeEvent(Event event){
this.userEvents.add(new UserEvent(this, event, true);
}
}
My questions are :
1) Do I have to model the Status and the Location as Nodes ?
String text, Set<String> tags, Date date
country, city, postalCode, double[] coordinates.
2) I don't understand exactly how to store the related nodes with Spring Data :
@RelatedToVia
@RelatedTo
3) When I add a liked movie, how do I have to do it :
likedMovies Set
? (the relationship will be automatically created ?)relationship Set
(ratings for example) ? (then the likedMovies Set will be automatically updated in the next fetch)4) For the friends Set and the friendships Set, do I have to specify the same type (type =
) ?
EDIT :
NEW QUESTION :
5) If I have same relationships but with different @StartNodes (User has categories, but Movie also have a category). Do I have to create 2 @RelationshipEntity with the different @StartNode ? (it is not a rich relationship in this case).
Upvotes: 1
Views: 365
Reputation: 41676
you should only model what is really an entity, like Venue with a location field. Location makes sense if you connect more to it.
It depends on your model, if you have really rich relationships, you can use @RelatedToVia
but you don't have to. See your entities rather as projections of certain use-cases, not the "one size fits all" which will bite you in the end.
If you have rich relationships you should add them to the @RelatedToVia Set. For a faster approach you can also use template.createRelationshipBetween()
. Or just create the RelationshipEntity, assign start end end-node and properties and save it with template.save()
.
yes, same relationship-type in the annotation
Do you have a "rich" relationship to the category? If not you don't have to model it. If yes, what would it look like? Then perhaps different types of category relationships make sense (also with different rel-types)
It depends on your model and your use-cases
Remove the @Fetch
annotations wherever possible it will just load a lot of data, that you might not need. Use template.fetch(user.field)
if needed.
For many use-cases I recommend not loading and hydrating full entities from the database but instead running a query and projecting the minimum amount of data returned into a list of view objects/dto's with (annotated or derived) repository methods and @QueryResult
on a POJO
Upvotes: 1