How to work with type hierarchies in Neo4j?
Asked Answered
N

4

14

Is there some way to model type hierarchies in Neo4j? If for example I want to build a class hierarchy of cars, I might have a base type of "Car" and then have sub classes that extend that, like "SportCar", etc.

I'd like to be able to create instances of "SportCar", but run a query to get all "Car"s. Is this possible? If so what is the technique?

I think what I'm trying to do is create a "label hierarchy" - but I just don't think that's supported in neo4j.

Needlefish answered 21/7, 2014 at 19:24 Comment(3)
Seems to be a duplicate of #21402771Ruling
One thing I've learned after reading more about neo4j is that there isn't really a "type" system. The closest thing they have is what they call "labels" which are basically just "tags" you can put on a node. So navigating hierarchies is totally doable, but you have to construct the queries in more specific ways, as there is no out of box support for "types", etc.Needlefish
AgensGraph (PostgreSQL fork extended with graph DB functionality) has label hierarchies: agensgraph.com/agensgraph-docs/…Tessy
R
13

Paul,

First, I'd recommend that you read "Graph Databases", a free O'Reilly e-book available at this link.

As a quick stab at an answer, there are numerous ways to do this sort of thing, and the best choice depends on the problem you are trying to solve. One way would be to construct a "Car" node, then relate your "SportCar" nodes to the "Car" node with a typed relationship like

CREATE (m:Car)
MATCH (m:CAR) WITH m CREATE (n:SportCar)-[:IS_A]->(m)

and create other types of cars, also relating them to the Car node.

You can then find all cars via

MATCH (m:Car)<-[:IS_A]-(n) RETURN n

You can also just put Car and SportCar (and LuxoCar, etc) labels on each node. And that's just two of many approaches.

Grace and peace,

Jim

Richers answered 21/7, 2014 at 19:49 Comment(1)
Ya I know you can apply a "IsA" relationship while you create nodes, but that doesn't let you do a "MATCH (c:Car) RETURN c" and get back all Cars, including cars that are sub classes of Car. I just don't think neo4j supports inheritance in searches. To be clear, OrientDB does support this - which I guess is just a key difference between the two platforms. Also, the label approach doesn't scale and would be a mess to manage when the hierarchy changes - imagine having to go back and update all the previous labels, etc.Needlefish
S
10

There are at least two ways to do that:

1) Use multiple lables for each object

CREATE(BMW325d:Car:PassengerCar:DieselCar)
CREATE(Porsche911:Car:SportsCar:...)

2) Create an Ontology

The second way of modeling a class hierarchy is using ontologies. Although Neo4j models data as a property graph and ontologies are more suitible for RDF Triple Stores there are ways to use them.

You can create the ontology using Protégé (Open Source). Then you save the Ontology in an .owl-File and upload it to Neo4j using this Plugin. Afterwords you assert your nodes in Neo4j to the Metagraph created in Protégé. A more detailed description is described here.

more on this topic...

For your purposes an RDF Triple Store is an interesting option, escpecially if you want to add semantics to your data like to use inferences and inheritance. I recommend to take a closer look on RDF Triple Stores, which are also graphs - but they store data in triples (subject - predicate - object) instead of nodes and relations. Top Braid Composer is an "easy-to-learn"-tool to get started with them.

Although, I hope that the gap between Property Graphs and RDF triple stores will get smaller soon at the moment it is a tradeoff. SO you should carefully set your requirements on the database before choosing one of them.

Hope this helps.

Saurian answered 26/8, 2017 at 16:55 Comment(0)
N
3

So the closets thing I could come up with is this example.

Step 1: Create a type hierarchy of car types.

create (c:CarType{Code:"Car"})
create (sc:CarType{Code:"SportCar"})
create (sc)-[:SubCarOf]->(c)

Step 2: Create an instance of a "SportCar" and record that (via a relationship property) it's "CarType".

merge (sc:CarType{Code:"SportCar"})
create (i:SportCar)
create (i)-[:CarType]->(sc)

Step 3: Write a query that finds all "CarType"s that derive from "Car" and any that are just of type "Car", then find instances of these.

match (c)-[:CarType]->(ct:CarType{Code:"Car"})
return c as Car
union
match (sct)-[:SubCarOf*]->(ct:CarType{Code:"Car"}), 
(c)-[:CarType]->(sct)
return c as Car
Needlefish answered 21/7, 2014 at 21:3 Comment(0)
I
2

Composition

You could consider composition in place of inheritance.

CREATE (c0:Car:SportsCar {colour: "yellow", brand: "Bugatti", country: "France"}),
(c1:Car:LuxuryCar {colour: "red", brand: "Mercedes-Benz", country: "Germany"})
  • Find all Cars
MATCH (c:Car) RETURN c;

All Cars

  • Find all SportCars:
MATCH (c:Car:SportsCar) RETURN c;

All Sports Car

  • Find all LuxuryCars:
MATCH (c:Car:LuxuryCar) RETURN c;

All Luxury Cars

Isothere answered 6/3, 2022 at 9:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.