How can you implement concise bounded description using SPARQL CONSTRUCT if you don't want to rely on "black-boxed" implementations using SPARQL DESCRIBE?

The basic query for symmetric CBD would simply look like this:

CONSTRUCT {
  :resource ?p1 ?o1 . # Outbound links
  ?s1 ?p2 :resource . # Inbound links
}
WHERE {
  :resource ?p1 ?o1 .
  ?s1 ?p2 :resource .
}

However, since the CBD is trying to describe not only a resource but an entity, its boundaries are broader. To define boundaries of entity CBD "abuses" the semantics of blank-nodes and reified rdf:Statements and possibly other "dependent" resource, that don't have a separate identity (e.g., rdf:List comes to mind). The CBD specification thus further recursively describes (expands on) these dependent resources, which for blank nodes can look like this:

:resource ?p1 ?o1 .
FILTER (isBlank(?o1))
?o1 ?p2 ?o2 .

However, since SPARQL can't express recursion it is probably necessary to write down graph patterns for nested blank nodes/rdf:Statements/etc. explicitly with OPTIONAL clauses. I wrote "probably" because I was wondering if the recursive expansion of CBD cannot be solved by using SPARQL extensions for transitivity. For example, in the case of OpenLink's Virtuoso it's possible to use OPTION (TRANSITIVE) for subqueries (documentation). However so far, I haven't managed to implement it using the transitive extensions. I've also learnt it's possible to register a custom SPARQL DESCRIBE handler in Jena, however the documentation of this feature seems to be fairly sparse.

My question is then what do you think is the best way to implemented CBD in SPARQL using CONSTRUCT query and, if necessary, some extensions? Do you think it can be done? Will there be some problems with performance of the transitive queries?

asked 11 Jan '13, 10:22

jindrichm's gravatar image

jindrichm
1.7k210
accept rate: 28%

edited 11 Jan '13, 10:22

1

If you're willing to run two construct queries, the first of which generates some "intermediate data" that the second query is run against, then you can do this, as I've described in another question. Alternatively, you might be able to do this with one query, if you can add support for one special property to your query engine.

(28 Jan, 22:21) Joshua Taylor Joshua%20Taylor's gravatar image

Just CONSTRUCT isn't enough (it needs arbitrary depth of the pattern).

Either, using OPTIONALs, limit yourself to a fixed maximum depth of a chain of blank nodes, or use a DESCRIBE query. The normal Jena DESCRIBE handler is not sufficient - you will have to implement your own.

link

answered 11 Jan '13, 11:24

AndyS's gravatar image

AndyS ♦
12.4k27
accept rate: 31%

Sure, I justed wanted to formulate the CBD by using the CONSTRUCT query form (with any other keywords, such as OPTIONAL) instead of the "black-box" DESCRIBE to have a greater control over the query result. However, my question was rather about the way in which I can avoid specifying fixed maximum depth and instead use other approach, such as transitive subqueries and possibly others I haven't thought of before.

(11 Jan '13, 12:37) jindrichm jindrichm's gravatar image

@AndyS In an answer to this question, it seems that if we can have a property that relates each blank node to itself (either by previously constructing such triples, or by extending the query engine, e.g., a property function in ARQ), we can do this with a pretty simple SPARQL query. I haven't implemented any property functions in ARQ though; I'll take a look, but do you think it'd be very hard to implement one that just relates each blank node to itself?

(28 Jan, 22:23) Joshua Taylor Joshua%20Taylor's gravatar image

I've managed to come up with a particularly ugly solution that uses Virtuoso's transitive subqueries. It includes both outbound and inbound triples and expands on blank nodes and instances of rdf:Statement.

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

CONSTRUCT {
  :resource ?outbound_p ?outbound_o .
  ?inbound_s ?inbound_p :resource .
  ?dependent_o ?dependent_p2 ?dependent_o2 .
}
WHERE {
  :resource ?outbound_p ?outbound_o .
  OPTIONAL {
    ?inbound_s ?inbound_p :resource .
  }
  OPTIONAL {
    {
      SELECT ?dependent_s ?dependent_o
      WHERE {
        ?dependent_s ?dependent_p ?dependent_o .
        OPTIONAL {
          ?dependent_o a ?type .
        }
        FILTER (isBlank(?dependent_o) || (bound(?type) && (?type = rdf:Statement)))
      }
    } OPTION (TRANSITIVE, t_distinct, t_in(?dependent_s), t_out(?dependent_o)) .
    FILTER (?dependent_s = :resource)
    ?dependent_o ?dependent_p2 ?dependent_o2 .
  }
}

Can you think of a way how it could be written in a better way?

link

answered 13 Jan '13, 15:01

jindrichm's gravatar image

jindrichm
1.7k210
accept rate: 28%

Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "Title")
  • image?![alt text](/path/img.jpg "Title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Tags:

×1,160
×2
×2

Asked: 11 Jan '13, 10:22

Seen: 945 times

Last updated: 28 Jan, 22:23