W3C home > Mailing lists > Public > public-lod@w3.org > May 2010

Re: GoodRelations vs. Google RDFa vs. Open Graph vs. hProduct/hListing: Using GoodRelations in 10 Triples

From: Martin Hepp (UniBW) <martin.hepp@ebusiness-unibw.org>
Date: Mon, 03 May 2010 17:41:19 +0200
Message-ID: <4BDEEE9F.3060901@ebusiness-unibw.org>
To: Story Henry <henry.story@bblfish.net>
CC: "public-lod@w3.org" <public-lod@w3.org>
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.

# 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

?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 
     gr:hasBusinessFunction gr:Sell;
         [ 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 

> 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.



martin hepp
e-business&  web science research group
universitaet der bundeswehr muenchen

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:

Resources for developers:

Overview -http://www.heppnetz.de/projects/goodrelations/webcast/
How-to   -http://vimeo.com/7583816

Recipe for Yahoo SearchMonkey:

Talk at the Semantic Technology Conference 2009:
"Semantic Web-based E-Commerce: The GoodRelations Ontology"

Overview article on Semantic Universe:

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
Received on Monday, 3 May 2010 15:41:50 UTC

This archive was generated by hypermail 2.4.0 : Thursday, 24 March 2022 20:29:48 UTC