Neo: Class name of Node? - neo4j

This question may seem a little bit naive, but do nodes have class names? I'm new to Neo4j and I've been looking at examples of how it is implemented in web frameworks, Rails especially. It seems like each node obviously holds the values of the class it belongs to, but, unless I'm misinformed, they don't seem to have class/table names like MySQL would have (eg table 'users'). If this isn't true, then why am I seeing so many examples of instantiated nodes with just the class fields and not the actual class name? If this is true, how would I refer to all nodes of a certain class (or create them)? Through their edges?

Check out Neo4J Labels. A label is a way of, well, labeling a node in neo4j according to a certain class it might belong to. So you might create a node with the label "Person". This isn't exactly what you mean by a "class" but a lot of people use it in roughly the same way.
By labeling nodes with class names that are relevant for your domain, you get the ability to query all of them, and only those nodes of a certain "class". Example:
MATCH (user:Person)-[:FRIEND]-(friend:Person) RETURN user, friend
This query specifies that "user" and "friend" must both be labeled "Person", which I think is pretty close to what you want.

Related

Node based properties on a relationship

I'm starting out with Neo4J to create a graph of users and their relationships. At the moment there is a single 'KNOWS' relationship between users i.e.
What I want to do now is specify properties on the relationship specifically for each of the users. For example, "interest" which indicates how much a user is interested in the other user. Can I specify this for each user on a single KNOWS relationship or would I need to create two relationships between the users and set the attribute on each of the relationships?
Any help would be appreciated.
Can I specify this (property: interest) for each user on a single KNOWS relationship or would I need to create two relationships between the users and set the attribute on each of the relationships?
You will need two relationships.
You could do it with one but then you have to keep two properties in the relationship and information about which property goes with which node. Much easier with two relationships.
From comment:
Can I keep them as bi-directional or would I need to use directional
in this case?
Relationships are always directional. It is only when you query that the concept of bi-directional appears, but that is not really bi-directional, it is without direction, e.g. (a)-[r]-(b). So you would use (a)-[r]->(b) and (b)-[r]->(a) or (a)<-[r]-(b). If you query with the direction, then you know how to apply the relationship property.
I typically do more of my work with Java as an embedded application instead of Cypher and it pays to use directional queries as it makes for less code to do the associations.
Note
Since your case is so simple, just try various methods and see what works. Remember to keep track of how long the quires take and if necessary add indexes. Also use the query profiling tool to make sure you are making effective queries.

In Neo4j, is it possible to have the same relationship name for different entities

Let`s use the movie DB as an example.
If I would insert all people that worked on a movie in the DB, it would be difficult to find relationship names for everyone. Would it be a problem to have entities like: sound_designer, sound_engineer, set_designer, set_assistance, cable_guy, etc with the same relationship "WORKS_IN" to a Movie entity. Is it possible? Is it a good solution? Would I have problems? Are there alternatives?
Gabor's answer in the comments is a good one, there are no problems with nodes of differing labels having relationships of the same type to the same node.
Multi-labeling nodes with their role isn't a bad idea, however that assumes that a person's role is constant throughout the years captured by the graph, which may not hold true. Or rather, the labels would capture what roles they have been in their entire history, but what specific role they played within a particular movie is likely something you want as a property of the relationship itself, like a role property. Which might even be a list, if a person might have multiple roles for the same movie, similar to actors playing a part (where there is a roles list property on :ACTED_IN relationships).

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.

How to implement an EAV model in Neo4j?

The Entity-Attribute-Value (EAV) model is really powerful, but complex to implement using SQL, so people often look for alternatives to EAV. It seems like the perfect candidate for graph databases. I understand how to build a movie database where you have nodes with the Neo4j label "Movie" with the property "release_date" right on the node. How would you make this more generic, such that movies have the Neo4j label "Entity" following the general EAV model?
I've thought a lot about this, but I'm not confident I have a good solution. I'll take a stab at it anyway. Here's the most basic model:
<node> <relationship> <node>
Attribute --> :VALUE --> Entity
name="Label",type="string" --> value="Movie" --> name="The Matrix"
With this model, you can write code for how to display and edit Attribute.type. For example, maybe all labels have a text field with finite options on the front-end and all dates have a date-picker. You could break Attribute.type out into its own node, Type, if that was preferable (particularly would make sense for handling composite types). In that case, you have the relationship TYPE between Attribute and Type nodes.
This becomes a problem if entities have multiple relationships, as is the case for reviews or if you want to relate the value to something else, such as the user who assigned the value. Now, I think, the relationship "VALUE" has to be it's own node of type "Value" (i.e. has the Neo4j label, "Value") with an incoming relationship from both Attribute and User nodes.
The full form has Type nodes, Attribute nodes, User nodes, Value nodes, and Entity nodes, where the relationships have basically no properties on them.
Why do you need it in the first place?
I always thought that EAV was just a workaround for relational databases not being schema free.
Neo4j as other nosql databases is schema free, so you can just add the attributes that you want to both nodes and relationships.
If you need to you can also record the EAV model in a meta-schema within the graph but in most cases it is good enough if the meta-schema lives within the application that creates and uses your attributes.
Usually I treat labels as roles which in a certain context provide certain properties and relationships. A node can have many labels each of which representing one of those roles.
E.g. for the same node
:Person(name)-[:LIVES_IN]->(:City)
:Employee(empNo)-[:WORKS_AT]->(:Company)
:Developer()-[:HAS_SKILL]->(:CompSkill)
...
So in your case :Entity would just be a label that implies the name property.
And :Movie is a label that implies a release_date property and e.g. ACTED_IN relationships.

RoR: Tagging tags with other tags

I'm trying to prototype a system in Rails. Essentially, its an abstract relational data model that takes in user input to create nodes of information. Each node can have meta-information associated with it, so some nodes may have CreateDate and DueDate while others may have StartDate, DueDate and PersonResponsible. In this way we're simply collecting lots of notes, and attributing information that a person would want to remember in relation to that note. Easy.
What I want to do to build on that is to make each node act as a tag which can be applied to any other node, building trees that can be browsed down with every node leading you to other nodes that are relationally its children. That way you can start by showing a list of your top level nodes (those not tagged by any others) and as each item is focused on, present a list of that node's children (all the other nodes which are tagged by it).
So my question is, which rails plugins should I look into to do this?
If I understood correctly - the data model you are describing is a graph.
Unfortunately ... I haven't found a plugin that implements graphs with all the characteristics you need (acts_ as _ graph plugin cannot do it) so you could try programming the model yourself.
You will need 3 tables and 2 active record classes for it (one table is used for the many to many relationship)
Classes
1. Node
has_many_and_belongs_to :node
2. Metadata
belongs_to :node
Since you need dynamic metadata you can use 2 columns: Name (string), Data (text) but you'll have to serialize data when you put it in the Data field (since you need class information as well as the data so you can use it).
I think this model should be able to hold your data. It's up to you to program the user interface part.

Resources