2012-03-20 13 views
11

Probabilmente c'è una risposta facile a questo, ma non riesco nemmeno a capire come formulare la query di Google per trovarlo.Come espandere in modo ricorsivo i nodi vuoti nella query del costrutto SPARQL?

Sto scrivendo query di costruzione SPARQL su un set di dati che include nodi vuoti. Quindi, se faccio una query come

CONSTRUCT {?x ?y ?z .} WHERE {?x ?y ?z .}

Poi uno dei miei risultati potrebbero essere:

nm:John nm:owns _:Node

che è un problema se tutti i

_:Node nm:has nm:Hats

le triple non ottengono in qualche modo il risultato della query (perché alcuni parser che sto usando come rdf alla lib per Python non piacciono davvero i bnodes pendenti).

C'è un modo per scrivere la mia query COSTRUZIONE originale per aggiungere in modo ricorsivo tutte le triple associate a qualsiasi risultato di bnode in modo tale che nessun bnode venga lasciato penzolare nel mio nuovo grafico?

+2

Se stai facendo questo in un modo in cui è possibile eseguire una query costruire e quindi eseguire una query SPARQL contro che, in realtà si * può * ottenere una descrizione concisa-delimitato (CBD) utilizzando le query SPARQL. Dai un'occhiata a [Sparql query per restituire ricorsivamente tutte le triple che compongono un rdf: definizione della classe] (http://answers.semanticweb.com/questions/26220/sparql-query-to-return-all-triples-recursively- that-make-up-an-rdfsclass-definition) (e forse [Implementing Concise Bounded Description in SPARQL] (http://answers.semanticweb.com/questions/20361/implementing-concise-bounded-description-in-sparql)). –

+1

L'idea alla base delle risposte nel commento precedente è che è possibile creare una * nuova proprietà * che agisce efficacemente come un predicato all'interno di un percorso di proprietà. Ad esempio, per ciascun nodo IRI i, si aggiunge una tripla "i selfIRI i". Quindi quando scrivi un percorso come "? X p/selfIRI? Y", hai assicurato che? Y è un nodo IRI. –

risposta

10

La ricorsione non è possibile. Il più vicino a cui riesco a pensare è SPARQL 1.1 property paths (nota: quella versione è scaduta) ma i test di bnode non sono disponibili (afaik).

Si potrebbe semplicemente rimuovere le dichiarazioni con le bnodes finali:

CONSTRUCT {?x ?y ?z .} WHERE 
{ 
    ?x ?y ?z . 
    FILTER (!isBlank(?z)) 
} 

o tentare la fortuna recupero il bit successivo:

CONSTRUCT {?x ?y ?z . ?z ?w ?v } WHERE 
{ 
    ?x ?y ?z . 
    OPTIONAL { 
    ?z ?w ?v 
    FILTER (isBlank(?z) && !isBlank(?v)) 
    } 
} 

(che ultima query è piuttosto punire, btw)

Forse starai meglio con DESCRIBE, che salterà spesso i bnodi.

+0

Grazie utente. Il mio piano attuale prevede l'utilizzo di una query a due livelli senza preoccuparsi della ricorsione a una maggiore profondità. Il filtro isBlank può essere d'aiuto, ma i FILTRI sembrano davvero macinare prestazioni poiché SPARQL sembra materializzare l'intero sottoprogramma del prefiltro prima di eseguire il filtro riga per riga. Quindi, a meno che il sottografo non filtrato sia piccolo, le query sui filtri risultano molto intense. – rogueleaderr

+2

Non si può dire "SPARQL sta materializzando l'intero sottografo del filtro preliminare ...": diverse implementazioni del motore SPARQL avranno algoritmi diversi con punti di forza e punti deboli differenti. Varia anche a seconda della versione della libreria che stai utilizzando. –

3

Come suggerisce l'utente205512, eseguire tale operazione in modo ricorsivo non è possibile e, come indicato, utilizzando facoltativo (s) per scendere a livelli arbitrari verso i dati, non è fattibile su database di dimensioni non banali.

Gli stessi Bnodi sono localmente con ambito, sul set di risultati o sul file. Non vi è alcuna garanzia che un BNode si ottenga dall'analisi o da un set di risultati sia lo stesso ID utilizzato nel database (sebbene alcuni database lo garantiscano per i risultati della query). Inoltre, una query come "select? S where {? S? P _: bnodeid1}" è la stessa cosa di "select? Where {? S? P? O}" - nota che bnode è trattato come variabile in quel caso , non come "la cosa con l'id" bnodeid1 "" Questa stranezza del design rende difficile la ricerca di bnodes, quindi se si ha il controllo dei dati, suggerirei di non usarli. Non è difficile generare nomi per cose che sarebbero altrimenti bnodes, e le risorse con nome v. Bnodes non aumenteranno il sovraccarico durante l'interrogazione.

Questo non aiuta a recedere e ad afferrare i dati, ma per questo, non consiglio di fare queste domande generali; non si adattano bene e di solito restituiscono più di quanto desideriate o di cui avete bisogno. Ti suggerirei di fare più domande dirette. La tua query di costrutto originale ridurrà il contenuto dell'intero database, generalmente non è quello che desideri.

Infine, mentre descrivere può essere utile, non esiste un'implementazione standard; la specifica SPARQL non definisce alcun comportamento particolare, quindi ciò che viene restituito è lasciato al fornitore del database e può essere diverso. Ciò può rendere il tuo codice meno portabile se pensi di provare diversi database con la tua applicazione. Se vuoi un comportamento specifico fuori descrizione, è meglio implementarlo tu stesso. Fare qualcosa come la descrizione limitata concessa per una risorsa è un pezzo di codice facile, anche se puoi incontrare qualche mal di testa attorno a Bnodes.

+1

Grazie per la risposta, Michael. La mia query di esempio è stata un po 'imprecisa ... quello che sto cercando di fare è estrarre tutte le informazioni su una data entità in un set di dati che ho scaricato. Ma il set di dati include voci come "John era il creatore di _: 1234". Quindi suppongo che le mie alternative siano usare la query a due livelli e sperare che non schiacci le prestazioni, o semplicemente ristrutturare il database per nominare tutti gli bnodes. Sembra che le specifiche SPARQL potrebbero usare un supporto più forte per questo, perché questo non sembra essere un problema particolarmente raro. – rogueleaderr

1

Per quanto riguarda il funzionamento con la libreria RDF.rb di Ruby, che consente le query SPARQL con metodi di convenienza significativi sugli oggetti RDF :: Graph, i seguenti devono espandere i nodi vuoti.

rdf_type = RDF::SCHEMA.Person # for example 
rdf.query([nil, RDF.type, rdf_type]).each_subject do |subject| 
    g = RDF::Graph.new 
    rdf.query([subject, nil, nil]) do |s,p,o| 
    g << [s,p,o] 
    g << rdf_expand_blank_nodes(o) if o.node? 
    end 
end 

def rdf_expand_blank_nodes(object) 
    g = RDF::Graph.new 
    if object.node? 
    rdf.query([object, nil, nil]) do |s,p,o| 
     g << [s,p,o] 
     g << rdf_expand_blank_nodes(o) if o.node? 
    end 
    end 
    g 
end 
Problemi correlati