how can I recognize object properties vs datatype

2019-02-01 14:43发布

问题:

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, beside the sibling classes Author, book, Isbn. Individuals in book class are book’s subject(about 600 subjects) , and individuals in author class are name’s author and also isbn class. then I'm confused in object properties and datatype properties. if hasEdition is in properties in my ontology then i say that every book in class book have relation with edition class. so i use object properties but individual in this class(edition class) is integer<9. then how can tell it? is it datatype or object? and can use object properties vs datatype properties? (a same name)

回答1:

On Object and Datatype Properties

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 .

Deciding which to use

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.

An example of the consequences of choosing one or 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).