Hi Henry,
Thanks for your feedback!
>I wonder if the following could make it even simpler though:
First I think, why not make the currency a literal?
foo:offering a gr:Offering;
rdfs:label "Volkswagen Station Wagon, 4WD, 400 $"@en;
rdfs:description "I sell my old Volkswagen Station Wagon, 4WD, for 400
$"@en;
gr:hasPriceSpecification
[ a gr:UnitPriceSpecification;
gr:value "400"^^gr:USD;
] .
When you have a relation from a string to a value, you have a literal. monetary
values are good
examples it seems to me of this. It would remove at least three of your URL
usages, as you had
to specify the xsd:string twice, and also the type of the currency.
There are several reasons for using the current GoodRelations pattern.
The most important one is that GoodRelations represents all point values
internally as intervals, in order to support reasoning over ranges with
simple RDFS-style reasoners. As for prices, that has been an explicit
request from the hotel domain.
So gr:hasCurrencyValue is an rdfs:subPropertyOf gr:hasMaxCurrencyValue
AND of gr:hasMinCurrencyValue. This gives a nice coherent model for
point values and intervals, without the need for a SPARQL endpoint and
either a bit of RDFS-style reasoning or a bit of SPARQL query expansion.
Example:
# 3..4 USD per kilogram, e.g. depending on the size of the potatoes
foo:price a gr:UnitPriceSpecification ;
gr:hasCurrency "USD"^^xsd:string ;
gr:hasMinCurrencyValue "3.0"^^xsd:float ;
gr:hasMaxCurrencyValue "4.0"^^xsd:float ;
gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
gr:valueAddedTaxIncluded "true"^^xsd:boolean .
# 4 USD per kilogram
foo:price a gr:UnitPriceSpecification ;
gr:hasCurrency "USD"^^xsd:string ;
gr:hasCurrencyValue "4.0"^^xsd:float ;
gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
gr:valueAddedTaxIncluded "true"^^xsd:boolean .
Both will work with the following query:
# find something that has a price or upper price limit of less than 4
USD / kg
SELECT ?offer WHERE
{
?offer a gr:Offering .
?offer gr:hasPriceSpecification ?p .
?p gr:hasMaxCurrencyValue ?v .
?p gr:hasCurrency "USD"^^xsd:string .
?p gr:UnitOfMeasurement "KGM"^^xsd:string .
FILTER (?p <= "4")
}
The important message is that, without any domain-specific tweak of the
GoodRelations vocabulary, you can model things as simple as this
foo:offering a gr:Offering;
rdfs:label "Volkswagen Station Wagon, 4WD, 400 $"@en;
rdfs:comment "I sell my old Volkswagen Station Wagon, 4WD, for 400
$"@en;
gr:hasBusinessFunction gr:Sell;
gr:hasPriceSpecification
[ a gr:UnitPriceSpecification;
gr:hasCurrencyValue "400"^^xsd:float;
gr:hasCurrency "USD"^^xsd:string. ].
and as fine-granular as this:
# Boat Rental: 24 USD / 6 hours for 0-3 days, 75 USD per day for any
longer rental
foo:company a gr:BusinessEntity ;
gr:legalName "Hepp Space Ventures, Inc."@en ;
gr:offers foo:boat_offer.
foo:boat_offer a gr:Offering ;
rdfs:label "Boat rental"@en ;
rdfs:comment "We rent out boats"@en ;
gr:hasBusinessFunction gr:LeaseOut ;
gr:hasPriceSpecification foo:rental_price1, foo:rental_price2 .
foo:rental_price1 a gr:UnitPriceSpecification ;
gr:hasCurrency "USD"^^xsd:string ;
# 24 USD per 6 hours => 4 USD / hour
gr:hasCurrencyValue "4"^^xsd:float ;
gr:hasUnitOfMeasurement "HUR"^^xsd:string ;
gr:billingIncrement "6"^^xsd:float
gr:valueAddedTaxIncluded "true"^^xsd:boolean ;
gr:hasEligibleQuantity [ a gr:QuantitativeValueInteger ;
gr:hasUnitOfMeasurement "DAY"^^xsd:string ;
gr:hasMinValueInteger "0"^^xsd:int ;
gr:hasMaxValueInteger "3"^^xsd:int . ].
foo:rental_price2 a gr:UnitPriceSpecification ;
gr:hasCurrency "USD"^^xsd:string ;
gr:hasCurrencyValue "75"^^xsd:float ;
gr:hasUnitOfMeasurement "DAY"^^xsd:string ;
gr:valueAddedTaxIncluded "true"^^xsd:boolean ;
gr:hasEligibleQuantity [ a gr:QuantitativeValueInteger ;
gr:hasUnitOfMeasurement "DAY"^^xsd:string ;
gr:hasMinValueInteger "4"^^xsd:int . ].
And both use the same set of conceptual elements, and will basically
trigger the very same SPARQL queries. That is a major difference to any
other conceptual approach for product / offer data on the Web - to keep
the simple things simple while supporting the very complex cases off the
box.
Also in your example you could put the company in a different file, and refer
to it by
reference.
Yes, I agree. In particular, in RDFa one will use the rev attribute to
do that.
Best
Martin
--
--------------------------------------------------------------
martin hepp
e-business& web science research group
universitaet der bundeswehr muenchen
e-mail:h...@ebusiness-unibw.org
phone: +49-(0)89-6004-4217
fax: +49-(0)89-6004-4620
www:http://www.unibw.de/ebusiness/ (group)
http://www.heppnetz.de/ (personal)
skype: mfhepp
twitter: mfhepp
Check out GoodRelations for E-Commerce on the Web of Linked Data!
=================================================================
Project page:
http://purl.org/goodrelations/
Resources for developers:
http://www.ebusiness-unibw.org/wiki/GoodRelations
Webcasts:
Overview -http://www.heppnetz.de/projects/goodrelations/webcast/
How-to -http://vimeo.com/7583816
Recipe for Yahoo SearchMonkey:
http://www.ebusiness-unibw.org/wiki/GoodRelations_and_Yahoo_SearchMonkey
Talk at the Semantic Technology Conference 2009:
"Semantic Web-based E-Commerce: The GoodRelations Ontology"
http://www.slideshare.net/mhepp/semantic-webbased-ecommerce-the-goodrelations-ontology-1535287
Overview article on Semantic Universe:
http://www.semanticuniverse.com/articles-semantic-web-based-e-commerce-webmasters-get-ready.html
Tutorial materials:
ISWC 2009 Tutorial: The Web of Data for E-Commerce in Brief: A Hands-on
Introduction to the GoodRelations Ontology, RDFa, and Yahoo! SearchMonkey
http://www.ebusiness-unibw.org/wiki/Web_of_Data_for_E-Commerce_Tutorial_ISWC2009