# Convert String Variable to URI using SPARQL

**URL:** <https://community.stardog.com/t/convert-string-variable-to-uri-using-sparql/3192>\
**Category:** Support\
**Created:** [August 9, 2021, 3:41pm UTC](https://community.stardog.com/t/convert-string-variable-to-uri-using-sparql/3192 "2021-08-09T15:41:14Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![oli666](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/oli666/32/1019_2.png) [@oli666](https://community.stardog.com/u/oli666)\
**Post date:** [August 9, 2021, 3:41pm UTC](https://community.stardog.com/t/convert-string-variable-to-uri-using-sparql/3192/1 "2021-08-09T15:41:14Z")

</div>

Using a string as an URI works using:

```auto
SELECT DISTINCT ?db_uri ?uri ?db_uri_var ?prop ?val

{
BIND(URI("http://dbpedia.org/resource/Delta_Air_Lines") as ?db_uri)
      
      SERVICE <http://DBpedia.org/sparql>
{
?db_uri ?prop ?val .
}
}

```

However, as the value for the string comes "from somewhere else", I would need to use a variable inside the URI-call. This seems not to work.

```auto
SELECT DISTINCT ?db_uri ?uri ?db_uri_var ?prop ?val

{
BIND("http://dbpedia.org/resource/Delta_Air_Lines" as ?uri)
BIND(URI(?uri) as ?db_uri)
      
      SERVICE <http://DBpedia.org/sparql>
{
?db_uri ?prop ?val .
}
}

```

---

<div class="post-metadata">

**Author:** ![jess](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/jess/32/10_2.png) [@jess](https://community.stardog.com/u/jess)\
**Post date:** [August 9, 2021, 3:47pm UTC](https://community.stardog.com/t/convert-string-variable-to-uri-using-sparql/3192/2 "2021-08-09T15:47:38Z")

</div>

Can you share the query plans for these two? I suspect it has nothing to do with the IRI/URI label coming from a variable, but instead the fact that you are going to need to ask for the entire contents of the DBpedia database to execute this query.

---

<div class="post-metadata">

**Author:** ![jess](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/jess/32/10_2.png) [@jess](https://community.stardog.com/u/jess)\
**Post date:** [August 9, 2021, 3:48pm UTC](https://community.stardog.com/t/convert-string-variable-to-uri-using-sparql/3192/3 "2021-08-09T15:48:23Z")

</div>

Additionally, if you can share something closer to the actual query you need, we can provide some guidance on getting that to run.

---

<div class="post-metadata">

**Author:** ![oli666](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/oli666/32/1019_2.png) [@oli666](https://community.stardog.com/u/oli666)\
**Post date:** [August 9, 2021, 4:01pm UTC](https://community.stardog.com/t/convert-string-variable-to-uri-using-sparql/3192/4 "2021-08-09T16:01:28Z")

</div>

First query:

```auto
Slice(offset=0, limit=100) [#100]
`─ Distinct [#500]
   `─ Projection(?db_uri, ?prop, ?val) [#500]
      `─ ServiceJoin [#500]
         +─ Service <http://DBpedia.org/sparql> {
         │ +─ Scan[SPO](?db_uri, ?prop, ?val)
         │ }
         `─ Bind(IRI("http://dbpedia.org/resource/Delta_Air_Lines") AS ?db_uri) [#1]

```

Second one:

```auto
Slice(offset=0, limit=100) [#100]
`─ Distinct [#500]
   `─ Projection(?uri, ?prop, ?val) [#500]
      `─ NestedLoopJoin(_) [#500]
         +─ Bind("http://dbpedia.org/resource/Delta_Air_Lines" AS ?uri) (IRI(?uri) AS ?db_uri) [#1]
         `─ Service <http://DBpedia.org/sparql> {
            +─ Scan[SPO](?db_uri, ?prop, ?val)
            }

```

---

<div class="post-metadata">

**Author:** ![oli666](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/oli666/32/1019_2.png) [@oli666](https://community.stardog.com/u/oli666)\
**Post date:** [August 9, 2021, 4:07pm UTC](https://community.stardog.com/t/convert-string-variable-to-uri-using-sparql/3192/5 "2021-08-09T16:07:20Z")

</div>

The simple version of the actual query will be along the following lines:

```auto
PREFIX : <http://dummy.org/dummy/>
PREFIX nee: <http://www.ics.forth.gr/isl/oae/core#>

SELECT *
WHERE
{
     ?ent :category ?cat ;
         nee:detectedAs ?literal ;
         nee:hasMatchedURI ?uri_str .
     BIND(URI(?uri_str) as ?db_uri)
  SERVICE <http://DBpedia.org/sparql>
  {
    ?db_uri ?dbpProperty ?dbpValue .
  }
}

```

---

<div class="post-metadata">

**Author:** ![jess](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/jess/32/10_2.png) [@jess](https://community.stardog.com/u/jess)\
**Post date:** [August 9, 2021, 4:15pm UTC](https://community.stardog.com/t/convert-string-variable-to-uri-using-sparql/3192/6 "2021-08-09T16:15:38Z")

</div>

> [@oli666](#):
>
> `ServiceJoin`

The service join is implemented by constraining the query sent to the `SERVICE`. As far as I know, DBpedia implicitly adds a LIMIT to the query and Stardog doesn't account for this. Without the `ServiceJoin`, DBpedia would only return the first page of results which aren't guaranteed to join with the rest of the query. Let me look further into the issue you've observed with given example.

Are you able to share the query plan for your actual query?

Jess

---

<div class="post-metadata">

**Author:** ![oli666](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/oli666/32/1019_2.png) [@oli666](https://community.stardog.com/u/oli666)\
**Post date:** [August 9, 2021, 4:23pm UTC](https://community.stardog.com/t/convert-string-variable-to-uri-using-sparql/3192/7 "2021-08-09T16:23:25Z")

</div>

Nothing super fancy so far ... getting strings as nee:hasMatchedURI (coming from external NER) and trying to convert those into valid URIs as the subject for DBpedia enrichment:

```auto
Slice(offset=0, limit=100) [#100]
`─ Projection(?t, ?ent, ?cat, ?literal, ?uri, ?db_uri, ?dbpProperty, ?dbpValue) [#1.0K]
   `─ NestedLoopJoin(_) [#1.0K]
      +─ Service <http://DBpedia.org/sparql> {
      │ +─ Scan[SPO](?db_uri, ?dbpProperty, ?dbpValue)
      │ }
      `─ Bind(IRI(?uri) AS ?db_uri) [#131538.1M]
         `─ NestedLoopJoin(_) [#131538.1M]
            +─ NaryJoin(?ent) [#278K]
            │ +─ Scan[PSOC](?ent, nee:detectedAs, ?literal) [#711K]
            │ +─ Scan[PSOC](?ent, nee:hasMatchedURI, ?uri) [#278K]
            │ `─ Scan[PSOC](?ent, twitter:category, ?cat) [#711K]
            `─ Scan[POSC](?t, rdf:type, twitter:Tweet) [#473K]

```

---

<div class="post-metadata">

**Author:** ![jess](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/jess/32/10_2.png) [@jess](https://community.stardog.com/u/jess)\
**Post date:** [August 9, 2021, 4:31pm UTC](https://community.stardog.com/t/convert-string-variable-to-uri-using-sparql/3192/8 "2021-08-09T16:31:59Z")

</div>

Can you share the plan for this query:

```auto
select * {
# We hint to the optimizer that the pattern is selective relative to the DBpedia SERVICE which
# we otherwise only have heuristics to decide on join algorithms
{ #pragma cardinality 10
?ent nee:detectedAs ?literal .
?ent nee:hasMatchedURI ?uri .
?ent twitter:category ?cat .
BIND(IRI(?uri) as ?db_uri)
}

  SERVICE <http://DBpedia.org/sparql>
  {
    ?db_uri ?dbpProperty ?dbpValue .
  }
}

```

---

<div class="post-metadata">

**Author:** ![oli666](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/oli666/32/1019_2.png) [@oli666](https://community.stardog.com/u/oli666)\
**Post date:** [August 9, 2021, 4:46pm UTC](https://community.stardog.com/t/convert-string-variable-to-uri-using-sparql/3192/9 "2021-08-09T16:46:24Z")

</div>

Plan as below. The query itself is timing out for me, unfortunately ...

```auto
Slice(offset=0, limit=100) [#100]
`─ Projection(?ent, ?literal, ?uri, ?cat, ?db_uri, ?dbpProperty, ?dbpValue) [#1.0K]
   `─ NestedLoopJoin(_) [#1.0K]
      +─ Bind(IRI(?uri) AS ?db_uri) [#278K]
      │ `─ NaryJoin(?ent) [#278K]
      │ +─ Scan[PSOC](?ent, twitter:category, ?cat) [#711K]
      │ +─ Scan[PSOC](?ent, nee:detectedAs, ?literal) [#711K]
      │ `─ Scan[PSOC](?ent, nee:hasMatchedURI, ?uri) [#278K]
      `─ Service <http://DBpedia.org/sparql> {
         +─ Scan[SPO](?db_uri, ?dbpProperty, ?dbpValue)
         }

```

---

<div class="post-metadata">

**Author:** ![LorenzB](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/lorenzb/32/806_2.png) [@LorenzB](https://community.stardog.com/u/LorenzB)\
**Post date:** [August 10, 2021, 8:19am UTC](https://community.stardog.com/t/convert-string-variable-to-uri-using-sparql/3192/10 "2021-08-10T08:19:08Z")

</div>

> [@jess](#):
>
> The service join is implemented by constraining the query sent to the `SERVICE` . As far as I know, DBpedia implicitly adds a LIMIT to the query and Stardog doesn't account for this. Without the `ServiceJoin` , DBpedia would only return the first page of results which aren't guaranteed to join with the rest of the query. Let me look further into the issue you've observed with given example.

that can't be the issue for the two dummy example queries. For the first query it works as Stardog is capable of putting the `BIND` inside the `SERVICE` clause whereas for the second query it isn't for some reason although there are also only two consecutive `BIND` clauses which could be simplified/evaluated first and then again could be put into the `SERVICE`

So the question is why is

```auto
BIND("foo" AS ?y)
SERVICE {
?y ?p ?o .
}

```

differently evaluated from

```auto
BIND("foo" AS ?x)
BIND(?x AS ?y)
SERVICE {
?y ?p ?o .
}

```

I know that evaluation of `SERVICE` with external inline data via `VALUES` or `BIND` is unfortunately only informative in the specs: [SPARQL 1.1 Federated Query](https://www.w3.org/TR/sparql11-federated-query/#values)

but it's clearly more efficient to put as much data as possible inside the `SERVICE` query if possible.  
Maybe there are some query evaluation hints for `SERVICE` clauses?

Side note: Other triple stores also have "trouble" with federated queries.

---

<div class="post-metadata">

**Author:** ![jess](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/jess/32/10_2.png) [@jess](https://community.stardog.com/u/jess)\
**Post date:** [August 10, 2021, 11:12pm UTC](https://community.stardog.com/t/convert-string-variable-to-uri-using-sparql/3192/11 "2021-08-10T23:12:23Z")

</div>

Hi Lorenz!

We don't always evaluate static expressions before runtime. For better or worse, it is what it is and should not lead to incorrect results. And in this case, it's not the root cause of incorrect results. The problem is that the DBpedia service limits the size of a result set. If you send a query of `?s ?p ?o`, you will receive a limited set of otherwise arbitrary results. Stardog doesn't account for the fact that _DBpedia returns incomplete results_ and therefore makes query optimization decisions that may manifest in incomplete results from Stardog given this limitation of DBpedia.

The assertion that _it's clearly more efficient to put as much data as possible inside the `SERVICE` query if possible_ is not universally true. Stardog doesn't have any knowledge of the size of the upstream data source. While a `?s ?p ?o` query is a possible heuristic for the likelihood that we should push constraints to the service, we don't always do it.

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex030/uploads/stardog/original/2X/e/ed66b48a616f505106a4acde3c9cee7e6da9bc67.svg) [@system](https://community.stardog.com/u/system)\
**Post date:** [August 24, 2021, 11:13pm UTC](https://community.stardog.com/t/convert-string-variable-to-uri-using-sparql/3192/12 "2021-08-24T23:13:10Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
