Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getting count of rdf:list using SPARQL

Is this the correct/best SPARQL query to get the count of items in rdf:list:

select (COUNT(?a) AS ?count) where {?a http://www.w3.org/1999/02/22-rdf-syntax-ns#first ?c}

Thanks in advance for your help.

regards, rahul

like image 278
user1278577 Avatar asked Mar 19 '12 13:03

user1278577


2 Answers

Interesting question, as it seems simple enough and yet it's hard to correctly express the query. William Greenly's answer does not provide what you want, although he is perfectly right in his explanations and rightly use a property path. To be able to properly ask the right query that answers your question, it must be assumed that all lists are well formed (they only have one first element, one rest and they end with a nil).

The problem in your query is that it will count all members of all lists in the dataset. You need something to relate the rdf:first to only the element of one list.

If you have a URI identifying the list your are interested in, you can the following:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  
PREFIX ex:  <http://www.example.org/#>
SELECT (COUNT(?member) AS ?count) 
WHERE {
  ex:uriOfTheList  rdf:rest*/rdf:first  ?member
}

But often, lists are not identified by a URI. In this case, it is possible to identify certain lists by using other properties. For instance, imagine you have a ex:listOfAuthors property, you can do:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX ex:  <http://www.example.org/#>
SELECT (COUNT(?member) AS ?count) 
WHERE {
  ex:publication  ex:listOfAuthors  ?list .
  ?list  rdf:rest*/rdf:first  ?member .
}

Note that if you simply do:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT (COUNT(?member) AS ?count) 
WHERE {
  ?list  rdf:rest*/rdf:first  ?member .
}

you'll add up all the sizes of lists and sublists. Now things get complicated if you don't have predicates to which you can attach the list and you don't have a URI and maybe you want to get the count for all lists, per list. There is one way that should work:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT (COUNT(?c) AS ?count) 
WHERE {
  ?thing  !rdf:rest  ?list .
  ?list  rdf:rest*/rdf:first  ?member .
}

What this is saying is that we want to find something that connects to a list, but not with the predicate rdf:rest. In principle, only the start of a list is connected via a predicate to some other entity, if the entity is not a list itself and the predicate is not rdf:rest. Moreover, lists are normally always connected somehow to other entities, as there would be no point in describing a list independently of aything else.

like image 55
Antoine Zimmermann Avatar answered Oct 18 '22 20:10

Antoine Zimmermann


This is actually a really good question because its not a particularly straightforward solution.

The important terms in RDF lists are:

rdf:first 
rdf:rest 
rdf:nil

for a list of more than one items, it is recommended that you model as follows:

a:a rdf:first a:b;
    rdf:rest [
       rdf:first a:c;
       rdf:rest rdf:nil.
    ].

using rdf:nil to indicate that a list no longer has any more items (so essentially it is a list of lists). However it also states that you can use rdf:first interderterminantly as follows:

a:a rdf:first a:b;
    rdf:first a:c;
    rdf:rest rdf:nil.

The point of rdf:nil is to specify that a list no longer has any items. Remember that Semantic Web is based on Open World assumptions, so unless other stated, you cannot assume that the list has no more items simply because they are not known or stated, hence the need for the individual, rdf:nil.

Fortunately, in the above example, there is a single query for both, that relies on a processor supporting SPARQL 1.1.

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  
SELECT (COUNT(?a) AS ?count) 
WHERE {?a rdf:first+ ?c}

remember though that unless the list contains rdf:nil, don't assume it to be complete.

like image 22
William Greenly Avatar answered Oct 18 '22 21:10

William Greenly