É possível obter a posição de um elemento em uma coleção RDF no SPARQL?

Suponha que eu tenha a seguinte declaração de tartaruga:

@prefix :  . :ls :list (:a :b :c) 

Existe uma maneira de obter as posições dos elementos na coleção?

Por exemplo, com esta consulta:

 PREFIX :  PREFIX rdf:  SELECT ?elem WHERE { ?x :list ?ls . ?ls rdf:rest*/rdf:first ?elem . } 

Eu recebo:

 -------- | elem | ======== | :a | | :b | | :c | -------- 

Mas gostaria de uma consulta para obter:

 -------------- | elem | pos | ============== | :a | 0 | | :b | 1 | | :c | 2 | -------------- 

É possível?

    Uma solução Pure SPARQL 1.1

    Eu estendi os dados para tornar o problema um pouco mais difícil. Vamos adicionar um elemento duplicado à lista, por exemplo, um adicional :a no final:

     @prefix :  . :ls :list (:a :b :c :a) . 

    Em seguida, podemos usar uma consulta como essa para extrair cada nó da lista (e seu elemento) junto com a posição do nó na lista. A idéia é que podemos combinar todos os nós individuais na lista com um padrão como o [] :list/rdf:rest* ?node A posição de cada nó, no entanto, é o número de nós intermediários entre a cabeça da lista e o ?node Podemos combinar cada um desses nós intermediários quebrando o padrão em

     [] :list/rdf:rest* ?mid . ?mid rdf:rest* :node . 

    Então, se agruparmos pelo ?node , o número de ligações distintas é a posição do ?node na lista. Assim, podemos usar a seguinte consulta (que também pega o elemento (o rdf:first ) associado a cada nó) para obter as posições dos elementos na lista:

     prefix :  prefix rdf:  select ?element (count(?mid)-1 as ?position) where { [] :list/rdf:rest* ?mid . ?mid rdf:rest* ?node . ?node rdf:first ?element . } group by ?node ?element 
     ---------------------- | element | position | ====================== | :a | 0 | | :b | 1 | | :c | 2 | | :a | 3 | ---------------------- 

    Isso funciona porque a estrutura de uma lista RDF é uma linked list como esta (onde ?head é o começo da lista (o object de :list ), e é outra binding de ?mid por causa do padrão [] :list/rdf:rest* ?mid ):

    representação gráfica da lista RDF

    Comparação com Extensões ARQ da Jena

    O consulente da questão também publicou uma resposta que usa as extensões ARQ de Jena para trabalhar com listas RDF. A solução postada nessa resposta é

     PREFIX :  PREFIX rdf:  PREFIX list:  SELECT ?elem ?pos WHERE { ?x :list ?ls . ?ls list:index (?pos ?elem). } 

    Essa resposta depende do uso do ARQ de Jena e da ativação das extensões, mas é mais conciso e transparente. O que não é óbvio é se alguém tem um desempenho obviamente preferível. Acontece que, para listas pequenas, a diferença não é particularmente significativa, mas para listas maiores, as extensões ARQ têm um desempenho muito melhor. O tempo de execução para a consulta SPARQL pura rapidamente se torna proibitivamente longo, enquanto não há quase nenhuma diferença na versão usando as extensões ARQ.

     ------------------------------------------- | num elements | pure SPARQL | list:index | =========================================== | 50 | 1.1s | 0.8s | | 100 | 1.5s | 0.8s | | 150 | 2.5s | 0.8s | | 200 | 4.8s | 0.8s | | 250 | 9.7s | 0.8s | ------------------------------------------- 

    Esses valores específicos obviamente diferem dependendo da sua configuração, mas a tendência geral deve ser observável em qualquer lugar. Como as coisas podem mudar no futuro, aqui está a versão específica do ARQ que estou usando:

     $ arq --version Jena: VERSION: 2.10.0 Jena: BUILD_DATE: 2013-02-20T12:04:26+0000 ARQ: VERSION: 2.10.0 ARQ: BUILD_DATE: 2013-02-20T12:04:26+0000 

    Como tal, se eu soubesse que precisava processar listas de tamanhos não triviais e que eu tinha ARQ disponível, usaria a extensão.

    Eu encontrei uma maneira de fazer isso usando a biblioteca de function de propriedade no ARQ. Como Steve Harris diz, isso não é padrão.

     PREFIX :  PREFIX rdf:  PREFIX list:  SELECT ?elem ?pos WHERE { ?x :list ?ls . ?ls list:index (?pos ?elem). } 

    TL; DR – resposta curta não com uma resposta longa mas sim com um if.

    Resposta curta

    Não sem sair do padrão, a menos que suas listas tenham um tamanho restrito, você pode fazer algo sujo como:

     { ?x :list (:a) BIND(1 AS ?length) } UNION { ?x :list ([], :a) BIND(2 AS ?length) } UNION { ?x :list ([], [], :a) BIND(3 AS ?length) } ... 

    etc.

    Alguns mecanismos de consulta RDF possuem funções não padrão que funcionarão em listas RDF, mas você deve consultar a documentação do sistema.

    Resposta longa

    Este é um sintoma de listas RDF com uma estrutura e definição terríveis. De alguma forma acabamos com duas maneiras diferentes de representar listas, as quais são horríveis de se trabalhar!

    Se você controlar os dados, use uma representação mais sensata, por exemplo

      :member [ rdf:value :a ; :ordinal 1 ; ], [ rdf:value :b ; :ordinal 2 ; ], [ rdf:value :c ; :ordinal 3 ; ] ... 

    então você pode consultar com:

     {  :member [ rdf:value :a ; :ordinal ?position ] }