Extend current Graph with RDF

I'm new with Neo4j and I have a question about using rdf to extend the current graph. Suppose I have a normal graph data stored in Neo4j (just a basic graph) and I wish to use rdf to produce a hierarchy (e.g. owl:subPropertyOf, rdfs:subClassOf). In this case, how can I match the exact predicate or the class from the old graph to extend with the new defined rdf? Are there any examples or tutorials for doing this? Thanks in advance

Hi Oli,

If I understand what you're trying to achieve, you need to load RDF ontologies into neo4j and link them to your data.

With neosemantics, you can import RDF ontologies :

And you can also import your RDF data in a way that creates your RDF Classes as nodes in neo4j (cf. config parameter "handleRDFTypes" in Neosemantics Reference - Neosemantics).
That should allow you to link the ontology nodes to your data nodes.


Thanks David,
I saw the tutorial and it's helpful I think. There is one thing I'm still confused. Let's say that we have car1 and car2, car1 did something, maybe car1 - stopAt - shop1 and maybe I wish that if I only know from my graph DB that the car model is golf and I wish that from my ontology I can get more information, I could say that car is also a VW. The question for me is that how can I associate the 'golf' in my graph DB and 'golf' in my ontology. How can I do the mappings which can automatically associate all the cars. In other words, I would use the ontologies to enrich my previous graph DB if that's possible.


To link your ontology data and your instance data, make sure that you configure handleRDFTypes=NODES (or LABELS_AND_NODES) so RDF types are created as neo4j nodes, and match the nodes from your ontology data. Otherwise, by default RDF types are loaded as neo4j labels, which would leave your data disconnected from the ontology data.

You can also specify that option in import procedures :
call n10s.rdf.import.fetch(<file>,"Turtle", { typesToLabels: false });

cf. Importing RDF Data - Neosemantics

That may mean you need to re-import your instance data. If that's inconvenient, you can also easily mutate your model via cypher. Ex :

MATCH (class:Class {uri: "http://your/class#Golf"}) // match your ontology class
MATCH (car:Golf)                                   // match your instances 
CREATE (car)-[:rdf__type]->(class)       // link them                 

Thanks David, that's comprehensive

May I ask what's the mechanism for the first criteria (make labels to nodes) enable an automatically assosiation, the name? (e.g 'Person' in both graph db and .ttl file) I mean, what if my instance data is not from rdf but simply created by Cypher?

Update 2021-5-12

I use Cypher to create person with "create (a:Person {name:'oli1', age:1}), (b:Person {name:'oli2', age:2})" and have simple relations “(a)-[r:hasFriend]-(b)” and also their cars "create (c:Car {brand:'BMW', model:'3 Series'}), (d:Car {name:'Audi', model:'A4'})" and link them to oli1 and oli2 repectivelty something like "(a)-[r:hasCar]-(C)"

And I have a ontology file which describe the Person and Cars (e.g :Person rdf:type owl:class;
rdfs:subClassOf :Agent). Then I import this .owl file. I found that my instance data is not automatically associated with my ontology data but they are two seperate graph. Hope to get some insights, thanks


Indeed if your instance data is not loaded from RDF, you'll have to manually link it to the class nodes.
The nodes imported by neosemantics (your ontology classes) will be identified by their uri. If everything was loaded from RDF, the class nodes from ontology/instance data would be merged automatically because they have the same uri.
They also have a name property which you could use to match your data in the following way :

MATCH (inst:Car)                   // match all your :Car instances (or :Person, or even any node)
UNWIND labels(inst) as label       // for each of their labels
MATCH (class:Class {name: label})  // find a Class node whose name property matches the label
CREATE (inst)-[:rdf__type]->(class)// link them

(Note that the exact property names will depend on how you configured "handleVocabUris" in your neosemantics settings ; I assumed handleVocabUris: "IGNORE" in the query)

I tried the code above but nothing has been changed, therefore, I checked the node information, it seems there is not a class with name 'Car' and I'm even not sure that it has been translated as a class in Neo4j

  "identity": 26,
  "labels": [
  "properties": {
    "uri": "http://localhost/ontologies/2019/1/10/automobile#Car",
    "rdfs__label": "Car"

And here is the code I was applied to describe a car in the .owl file

:Car rdf:type owl:Class ;
     rdfs:label "Car" ;
     rdfs:subClassOf :Automobile .

I did not find the issue, could you provide some advices?

Adapting the query with the vocabulary generated by your ontology import :

MATCH (inst:Car)                   // match all your :Car instances (or :Person, or even any node)
UNWIND labels(inst) as label       // for each of their labels
MATCH (class:owl__Class {rdfs__label: label})  // find a Class node whose name property matches the label
CREATE (inst)-[:rdf__type]->(class)// link them