My ontology is book classification library. I have problems in this. I want to build a book classification ontology by protégé 4.1, this classification has 14 categories, b
In Protégé there are are different tabs for creating Object Properties and Datatype Properties. If a property should relate individuals to individuals, then it needs to be an object property, and if it relates individuals to literals, then it needs to be a datatype property.
If you have a property hasEdition
whose domain is Book
, then the question becomes what the range should be. If you expect triples like:
Book72 hasEdition "1"^^xsd:int
Book16 hasEdition "3"^^xsd:int
where the value are literals, then hasEdition
should be a datatype property. If, on the other hand, you have a class Edition
with some particular individuals, e.g.,
Edition a owl:Class .
first a Edition .
second a Edition .
third a Edition .
…
so that you can have
Book72 hasEdition first .
Book16 hasEdition third .
then hasEdition
should be an object property.
If you need to look at the RDF serialization and determine which types the properties are, you should query for the classes owl:ObjectProperty
and owl:DatatypeProperty
(and, for the sake of completeness, owl:AnnotationProperty
). That is, depending on whether hasEdition
is an object property or a datatype property you would see:
hasEdition a owl:ObjectProperty .
or
hasEdition a owl:DatatypeProperty .
Whether you want a hasEdition
property to be a datatype property or an object property really depends on what kind of data you're going to be storing, and that depends on your application. If you're just representing simple information like "first"
, "second"
, etc., then you probably want to use a datatype property that relates a book to its edition. This is probably a good route if you're representing books in the abstract, i.e, not individual instances of books (as opposed to a bookseller's inventory system, which would be be concerned with individual instances of books).
If, on the other hand, what you're actually representing are instances of books. E.g., if you're a bookseller and have in stock 25 copies of Semantic Web for the Working Ontologist and 27 copies of Programming the Semantic Web), then you might actually be interested in representing individual editions of books, on which the title, ISBN, and the like would probably be stored on the edition, not the book individual.
This is just an opinion, and you really do have a lot of flexibility in choosing your data model. It typically takes some experience to get nice data models, and experience takes time. Even so, you've got good tools for manipulating and transforming the data, so you can experiment with different representations, and map from one to the other.
I suggest you take a look at the RDF Primer. Resources and literals are distinct types of things. Resources are anonymous or identified by an IRI, and can be the subjects of statements (and thus be member of classes, by virtue of the statement
@prefix lib: <http://example.org/library/> .
lib:HermanMelville rdf:type lib:Author .
Literals, such as the string "Herman Melville
" cannot be the subjects of sentences, and so cannot be members of classes. With authors as resources (individuals), you can do
lib:MobyDick lib:hasAuthor lib:HermanMelville .
lib:HermanMelville lib:hasName "HermanMelville"@en .
In this case, hasAuthor
is an object property and hasName
is a datatype property.
On the other hand, you can make hasAuthor
a datatype property and instead do
lib:MobyDick lib:hasAuthor "Herman Melville"@en .
If you do this, though, then you don't have a convenient way to add any additional information about the author, since the literal "Herman Melville"@en
cannot be the subject of a triple, so you can't for instance, say
"Herman Melville"@en places:livedAt places:Arrowhead .
whereas in the first case, you could say
lib:HermanMelville places:livedAt places:Arrowhead .
It's really just a matter of how you want to be able to query your data. In the case that hasAuthor
is an object property, I can write a query like this to find books written by authors who lived at Arrowhead:
PREFIX lib: <http://...>
PREFIX places: <http//...>
SELECT ?book WHERE {
?book lib:hasAuthor ?author .
?author places:livedAt places:Arrowhead .
}
or even more concisely (but equivalently):
PREFIX lib: <http://...>
PREFIX places: <http//...>
SELECT ?book WHERE {
?book lib:hasAuthor [ places:livedAt places:Arrowhead ] .
}
On the otherhand, if hasAuthor
is a datatype property that relates a book to the name of its author, we can still have an Author
class whose instances are related to their names by the hasName
property, but it makes querying the data a bit more complicated, since the hasAuthor
property is forcing a layer of indirection (get the name of the author of the book, then find the author who has that name), so we have queries like:
PREFIX lib: <http://...>
PREFIX places: <http//...>
SELECT ?book WHERE {
?book lib:hasAuthor ?authorName .
?author lib:hasName ?authorName .
?author places:livedAt places:Arrowhead .
}
This query can't be simplified so nicely. It really comes down to how you want to be able to query your data, and what's convenient for you. Note that some queries that you can write in SPARQL are much harder to write as OWL DL expressions. When hasAuthor
is an object property, the class of books whose authors lived at Arrowhead with is given by the expression:
lib:hasAuthor (places:livedAt value places:Arrowhead)
which simply is the class of things that have an author that lived at Arrowhead. If hasAuthor
is a datatype property, it is much more difficult, if not impossible to write such an expression, because you need to find two things (a book and an author) that have the same literal value (the string that is the author's name).