An object-graph mapper based on owlready2
Project description
ogmready is a python library that is built upon owlready2 and strives to be an easy to use Object-Graph Mapper, enabling the use of a Knowledge Graph based on an Ontology as a viable alternative to relational databases. ogmready lets the user define their domain classes and specify later how they should be mapped to ontology concepts, leaving the application logic and the persistance strategy decoupled.
Quickstart
First, install the package:
pip install ogmready
Then define an Ontology, using owlready2 or your tool of choice:
onto = owlready2.get_ontology("http://example.org/")
with onto:
class Person(owlready2.Thing):
pass
class Dog(owlready2.Thing):
pass
class name(owlready2.DataProperty, owlready2.FunctionalProperty):
range = [str]
class age(owlready2.DataProperty, owlready2.FunctionalProperty):
range = [int]
class id(owlready2.DataProperty, owlready2.FunctionalProperty):
range = [int]
class hasDog(owlready2.ObjectProperty, owlready2.FunctionalProperty):
domain = [Person]
range = [Dog]
You can also add definitions under different namespaces:
other_namespace = "http://other.org/"
with onto.get_namespace(other_namespace):
class color(owlready2.DataProperty):
range = [str]
Define your domain classes:
@dataclass
class Dog:
id: int
name: str
colors: Set[str]
@dataclass
class Person:
id: int
name: str
age: int
dog: Dog
And finally the mappers
# Create a subclass of Mapper
class DogMapper(Mapper):
# Specify the domain and ontology classes to perfom the mapping
__source_class__ = Dog
__target_class__ = ("Dog", "http://example.org/")
# Define the mappings
# Data property, functional by default
id = DataPropertyMapping("id", primary_key=True),
name = DataPropertyMapping("name"),
# functional = False means that the property is a Set
# we can pass a tuple (name, namespace) to say that a name is in a
# different namespace than the default one
colors = DataPropertyMapping(("color", other_namespace), functional=False)
class PersonMapper(Mapper):
__source_class__ = Person
__target_class__ = ("Person", "http://example.org")
id = DataPropertyMapping("id", primary_key=True),
name = DataPropertyMapping("name"),
age = DataPropertyMapping("age"),
# We can reference other object mappers
dog = ObjectPropertyMapping("hasDog", DogMapper)
At this point, we can use the methods from_owl and to_owl of the mappers:
# create the objects
d = Dog(1, "pluto", {"black", "white"})
p = Person(2, "mario", 10, d)
# create the mapper objects, passing the ontology as an argument
person_mapper = PersonMapper(onto)
dog_mapper = DogMapper(onto)
# map to owlready2 objects
onto_dog = dog_mapper.to_owl(d)
onto_person = person_mapper.to_owl(p)
# map back
p == person_mapper.from_owl(onto_person)
d == dog_mapper.from_owl(onto_dog)
About lists
Since Knowledge Graph are usually stored in RDF format, which is based on
triples <subject, predicate, object>, storing lists is not straightforward.
While we use an OWL Ontology, we cannot use rdf:List, because it is used in the
OWL specification. A way around this is to use an Ontology that
lets us express the relations between lists and their elements: an example is
the Collections
Ontology, which
defines the semantics of lists. To express something like L = [a], using
the Collections Ontology we would say something like (mind that this is a
simplified RDF):
<L, is_a, List><L, item, a_in_L><a_in_L, is_a, ListItem><a_in_L, index, 0><a_in_L, itemContent, a>
So a_in_L acts as a connecting object between L and its content a. An
intermediate element like a_in_L is needed because we could have more
occurrences of a inside of L. Moreover, with index we can express the
order of the elements.
In ogmready, an example could be (using "http://purl.org/co/", the
Collections ontology):
@dataclass
class Person:
friends: List[Person]
co = "http://purl.org/co/"
class PersonMapper(Mapper):
__source_class__ = Person
__target_class__ = ("Person", "http://example.org/")
# the parameters are:
# - relation to connect list to items (e.g. 'item')
# - OWL class of the connecting item (e.g. 'ListItem')
# - relation to get to the actual item (e.g. 'itemContent')
# - mapper for the item contents
# - property to express the ordering of the elements
friends = ListMapping(("item", co), ("ListItem", co), ("itemContent", co), PersonMapper, ("index", co))
Defining your own mappings
It suffices to create a subclass of Mapping and implement the methods
from_owl and to_owl. The method to_query is relevant if the field that you
are mapping will be used in the queries to search for an already available
object in the ontology. The method is_primary_key by default returns False,
so changing its implementation makes sense if a property that you are mapping
could be a primary key, like DataPropertyMapping.
A note on object retrieval
TL;DR. It is always a good idea to specify a field as a primary key, if it is possible.
Since we could be mapping a deeply nested object, of course we don't want to
create new objects inside the Knowledge Graph if they are referenced by others
but are already storedy. By default, the Mapper class tries to search for the
referenced objects based on the fields that were specified as primary_key, but
in case no primary_key is defined, it defaults to a deep search (search of
all object fields inside the Knowledge Graph), which could become slow and in
certain cases it could loop if there are circular references.
Missing features (contributions are welcome!)
- Allowing the use of multiple mappers for a field, e.g. for
friend: Person | Dogit would be nice to say "usePersonMapperorDogMapper" based on what you find
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ogmready-0.1.6.tar.gz.
File metadata
- Download URL: ogmready-0.1.6.tar.gz
- Upload date:
- Size: 17.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6d1f3c03e6f7e31f831b421ec5b837a64971173f97840fe37b4baa08255ae745
|
|
| MD5 |
50161bd4d0b9e3c3306d5461da400920
|
|
| BLAKE2b-256 |
da49e993049ee07edbbf4ac87fb785c8e87ef24f4318fafe7a79dfb66f8fb72d
|
Provenance
The following attestation bundles were made for ogmready-0.1.6.tar.gz:
Publisher:
publish-pypi.yml on gianzav/ogmready
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ogmready-0.1.6.tar.gz -
Subject digest:
6d1f3c03e6f7e31f831b421ec5b837a64971173f97840fe37b4baa08255ae745 - Sigstore transparency entry: 244665728
- Sigstore integration time:
-
Permalink:
gianzav/ogmready@d6a1bb37f33d4fbdf11c2fe371b958f64fb5caa9 -
Branch / Tag:
refs/tags/0.1.6 - Owner: https://github.com/gianzav
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@d6a1bb37f33d4fbdf11c2fe371b958f64fb5caa9 -
Trigger Event:
push
-
Statement type:
File details
Details for the file ogmready-0.1.6-py3-none-any.whl.
File metadata
- Download URL: ogmready-0.1.6-py3-none-any.whl
- Upload date:
- Size: 13.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a674983a330fb36a2ca532fe3da9dbb7e19ceddebbad4f7157428cf9cdd45864
|
|
| MD5 |
013811fb5876310f86206cf49f20172a
|
|
| BLAKE2b-256 |
17ed9e537497f68b43988c1102ab1a054965db3fdbc036a2c6ef8db2e1ae09d1
|
Provenance
The following attestation bundles were made for ogmready-0.1.6-py3-none-any.whl:
Publisher:
publish-pypi.yml on gianzav/ogmready
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ogmready-0.1.6-py3-none-any.whl -
Subject digest:
a674983a330fb36a2ca532fe3da9dbb7e19ceddebbad4f7157428cf9cdd45864 - Sigstore transparency entry: 244665731
- Sigstore integration time:
-
Permalink:
gianzav/ogmready@d6a1bb37f33d4fbdf11c2fe371b958f64fb5caa9 -
Branch / Tag:
refs/tags/0.1.6 - Owner: https://github.com/gianzav
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@d6a1bb37f33d4fbdf11c2fe371b958f64fb5caa9 -
Trigger Event:
push
-
Statement type: