# Custom properties of OWL/RDF Ontology

**URL:** <https://community.neo4j.com/t/custom-properties-of-owl-rdf-ontology/19739>\
**Category:** Linked Data, RDF, Ontology\
**Created:** [June 9, 2020, 2:14pm UTC](https://community.neo4j.com/t/custom-properties-of-owl-rdf-ontology/19739 "2020-06-09T14:14:12Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![maksims.fiosins](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/maksims.fiosins/32/8521_2.png) [@maksims.fiosins](https://community.neo4j.com/u/maksims.fiosins)\
**Post date:** [June 9, 2020, 2:14pm UTC](https://community.neo4j.com/t/custom-properties-of-owl-rdf-ontology/19739/1 "2020-06-09T14:14:12Z")

</div>

Hi,

I am trying to import an ontology, which is in RDF/XML format (owl):

```auto
call n10s.graphconfig.init( { keepCustomDataTypes:true, handleRDFTypes: "LABELS_AND_NODES" });
CALL n10s.onto.import.fetch("...","RDF/XML");

```

In the ontology file, each class contains synonym properties:

`<oboInOwl:hasExactSynonym rdf:datatype="http://www.w3.org/2001/XMLSchema#string">human mammary epithelial cell</oboInOwl:hasExactSynonym>`

However the nodes of type Class do not contain that custom properties, and also separate nodes are not created. How can I get those custom proprieties into Neo4J?

Best,  
Maksims

---

<div class="post-metadata">

**Author:** ![jesus\_barrasa](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/jesus_barrasa/32/27513_2.png) [@jesus\_barrasa](https://community.neo4j.com/u/jesus_barrasa)\
**Post date:** [June 9, 2020, 4:11pm UTC](https://community.neo4j.com/t/custom-properties-of-owl-rdf-ontology/19739/2 "2020-06-09T16:11:02Z")

</div>

Hi @maksims.fiosins, If you want to keep your ontology simple, all you need to do is add to your script an additional step to import the extra properties using `n10s.rdf.stream`. Here's what it would look like if you wanted to add the `oboInOwl:hasExactSynonym` property to the imported classes:

```auto
CALL n10s.rdf.stream.fetch("...your onto...","RDF/XML") YIELD subject, predicate, object
WHERE predicate = "http://www.geneontology.org/formats/oboInOwl#hasExactSynonym"
MATCH (c:Class { uri: subject }) SET c.exactSynonym = coalesce(c.exactSynonym,[]) + [object]

```

With `n10s.rdf.stream` you can take control on how to handle each individual triple and decide how you want to model it. Check out [the manual](https://neo4j.com/docs/labs/nsmntx/current/previewing-rdf/#_streaming_triples) for more examples.

Another alternative would be to load the ontology as RDF with `n10s.rdf.import`. That way you'd be importing every single triple in the ontology as opposed to the simplified model that `n10s.onto.import` builds. It really depends on how you're going to use your ontology.

Let us know if this works for you.

Cheers,

JB.

---

<div class="post-metadata">

**Author:** ![maksims.fiosins](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/maksims.fiosins/32/8521_2.png) [@maksims.fiosins](https://community.neo4j.com/u/maksims.fiosins)\
**Post date:** [June 10, 2020, 10:16am UTC](https://community.neo4j.com/t/custom-properties-of-owl-rdf-ontology/19739/3 "2020-06-10T10:16:22Z")

</div>

Hi @jesus_barrasa,

Thank You for Your quick answer, the stream idea is very helpful. However, if I do  
`n10s.rdf.stream.fetch`, I get first 1000 triples. The manual does not say anything about this limit. Maybe You have an idea why this happens?

Best,  
Maksims

---

<div class="post-metadata">

**Author:** ![jesus\_barrasa](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/jesus_barrasa/32/27513_2.png) [@jesus\_barrasa](https://community.neo4j.com/u/jesus_barrasa)\
**Post date:** [June 10, 2020, 10:54am UTC](https://community.neo4j.com/t/custom-properties-of-owl-rdf-ontology/19739/4 "2020-06-10T10:54:31Z")

</div>

Oh, thanks for bringing this to our attention, we're updating the manual and this is clearly a missing element. The request config parameter is `limit` and you can add it like this:

`call n10s.rdf.stream.fetch('url','RDF/XML,{ limit: 999999999 })`

And yes, if not set, the default value is 1000.

Hope this helps.

JB.

---

<div class="post-metadata">

**Author:** ![maksims.fiosins](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/maksims.fiosins/32/8521_2.png) [@maksims.fiosins](https://community.neo4j.com/u/maksims.fiosins)\
**Post date:** [June 17, 2020, 7:25am UTC](https://community.neo4j.com/t/custom-properties-of-owl-rdf-ontology/19739/5 "2020-06-17T07:25:26Z")

</div>

Hi @jesus_barrasa,

Thank You for Your reply. The limit really helps.  
So now I have the following fragment, which loads my ontology with synonyms as separate nodes:

```auto
CALL n10s.graphconfig.init();
CALL n10s.onto.import.fetch("...my ontology file ...","RDF/XML");
CREATE INDEX FOR (n:Class) ON (n.uri)
CALL n10s.rdf.stream.fetch("...my ontology file ...","RDF/XML",{ limit: 999999999 }) YIELD subject, predicate, object
WHERE predicate = "http://www.geneontology.org/formats/oboInOwl#hasExactSynonym"
MATCH (c:Class { uri: subject }) 
MERGE (c)-[r:SynonymRel]-(s:Synonym{rdfs__label:object});

```

---

<div class="post-metadata">

**Author:** ![maksims.fiosins](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/maksims.fiosins/32/8521_2.png) [@maksims.fiosins](https://community.neo4j.com/u/maksims.fiosins)\
**Post date:** [June 17, 2020, 7:37am UTC](https://community.neo4j.com/t/custom-properties-of-owl-rdf-ontology/19739/6 "2020-06-17T07:37:22Z")

</div>

However, I have one more problem. Namely, there is a `partOf` relation in the ontology, which is defined by two predicates:

```auto
<owl:Class rdf:about="<uri of a class>">
        <rdfs:subClassOf>
            <owl:Restriction>
                <owl:onProperty rdf:resource="<uri of partOf predicate>"/>
                <owl:someValuesFrom rdf:resource="<uri of a parent>"/>
            </owl:Restriction>
        </rdfs:subClassOf>
...
</owl:Class>

```

By streaming this using `n10s.rdf.stream.fetch` I get the triples one by one. When I am on the triple

```auto
                <owl:someValuesFrom rdf:resource="<uri of a parent>"/>

```

how can I get:

- A triple `<owl:onProperty rdf:resource="<uri of partOf predicate>"/>`, because from it I know that this is a "partOf" relation;

- A parent `<owl:Class rdf:about="<uri of a class>">`, because from it I get uri of the main class.

Maybe it is possible to get a predefined type structure or to access parent/sister triples?

Best regards,  
Maksims

---

<div class="post-metadata">

**Author:** ![jesus\_barrasa](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/jesus_barrasa/32/27513_2.png) [@jesus\_barrasa](https://community.neo4j.com/u/jesus_barrasa)\
**Post date:** [June 17, 2020, 12:08pm UTC](https://community.neo4j.com/t/custom-properties-of-owl-rdf-ontology/19739/7 "2020-06-17T12:08:02Z")

</div>

Great question @maksims.fiosins !

First option would be to use SPARQL. If the ontology lives in a repository that offers SPARQL access you can write a query that returns just the fragment you're looking for. Then you could embed your SPARQL endpoint request in the `n10s.rdf.stream.fetch` procedure call as [described in the manual](https://neo4j.com/docs/labs/nsmntx/current/import/#advancedfetching). But I understand SPARQL access is not always available and you may be just fetching a document containing all the triples.

Alternatively, we'd need to include that logic in the `n10s.onto.import` procedures. I've been looking at this for a while (how to extend the elements in the ontology that the `onto.import` loads in order to include constructs like Restriction definitions) but could not come up with a satisfactory solution that was useful and did not involve a massive effort.

I'd love to hear your thoughts on this second option. How would you want the restriction in your example modelled in the graph? Or maybe from a different angle: how do you intend to use it once loaded in neo4j?

Cheers,

JB.

---

<div class="post-metadata">

**Author:** ![maksims.fiosins](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/maksims.fiosins/32/8521_2.png) [@maksims.fiosins](https://community.neo4j.com/u/maksims.fiosins)\
**Post date:** [June 22, 2020, 1:49pm UTC](https://community.neo4j.com/t/custom-properties-of-owl-rdf-ontology/19739/8 "2020-06-22T13:49:23Z")

</div>

Dear @jesus_barrasa,

Thank You again for Your answer.

SPARQL will not solve the problem, because the problem is not to select the necessary triples - I can do it using WHERE - but to transform the structure. I am not sure, if SPARQL allows this.

In the meantime I solved the problem with a parent by saving child subject id in the node.

```auto
CALL n10s.rdf.stream.fetch('file:////var/lib/neo4j/import/%s.owl','RDF/XML',{ limit: 999999999 })
                          YIELD subject,predicate,object
                          WHERE predicate IN ['http://www.w3.org/2000/01/rdf-schema#subClassOf','http://www.w3.org/2002/07/owl#someValuesFrom']
                          CALL apoc.do.when(predicate='http://www.w3.org/2000/01/rdf-schema#subClassOf',
                                 'MATCH (c:Class {uri:subject}) SET c.subClassOf=object RETURN c',
                                 'MATCH(c:Class{subClassOf:subject}) MATCH (p:Class{uri:object})
                                  MERGE (c)-[:SCO]->(p) RETURN c', {subject:subject,predicate:predicate,object:object}) YIELD value RETURN value"""

```

Here I do not use a sister predicate, I assume that `subClassOf` already points to the parent hierarchy.

I think `n10s.onto.import` may be extended that it at least allows other predicates to be used in the ontology graph creation. However I don't have currently a good suggestion about the syntax, it requires some complex structures to describe how the hierarchy and the labels are created.

Best regards,  
Maksims

---

<div class="post-metadata">

**Author:** ![jesus\_barrasa](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/jesus_barrasa/32/27513_2.png) [@jesus\_barrasa](https://community.neo4j.com/u/jesus_barrasa)\
**Post date:** [July 7, 2020, 2:12am UTC](https://community.neo4j.com/t/custom-properties-of-owl-rdf-ontology/19739/9 "2020-07-07T02:12:30Z")

</div>

It is indeed possible to change the structure of the RDF graph with SPARQL CONSTRUCT.  
Here's [a repository](https://github.com/jbarrasa/connections-lifesci) where I use it extensively to import data from Wikidata and MeSH into Neo4j, the recording of the presentation is [here](https://www.youtube.com/watch?v=tDPK4CTamKg).

Regards,

JB.
