<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta />
    <article-meta>
      <title-group>
        <article-title>Querying APIs with SPARQL</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Matthieu Mosser</string-name>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Fernando Pieressa</string-name>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Juan Reutter</string-name>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Adrian Soto</string-name>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Domagoj Vrgoc</string-name>
        </contrib>
      </contrib-group>
      <abstract>
        <p>Although the amount of RDF data has been steadily increasing over the years, the majority of information on the Web is still residing in other formats, and is often not accessible to Semantic Web services. A lot of this data is available through APIs serving JSON documents. In this work we propose a way of extending SPARQL with the option to consume JSON APIs and integrate the obtained information into SPARQL query answers. Looking to evaluate these queries as e ciently as possible we present an algorithm that produces \worst-case optimal" query plans that reduce the number of requests as much as possible. We also do a set of experiments that empirically con rm the optimality of our approach.</p>
      </abstract>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>Introduction</title>
    </sec>
    <sec id="sec-2">
      <title>SERVICE-to-API Queries</title>
      <p>
        We extended the SERVICE operator to allow SPARQL to query Web APIs. We
call a query that uses this extended SERVICE a SERVICE-to-API query. We
assume the reader is familiar with the syntax and semantics of SPARQL 1.1 query
language [
        <xref ref-type="bibr" rid="ref6">6</xref>
        ]. We concentrate on the so-called REST Web APIs, which
communicate via HTTP requests,assuming that all API responses are JSON documents.
To illustrate how our extension works we will use the following example:
Example 1. We nd ourselves in Scotland in order to do some hiking. We obtain
a list of all Scottish mountains using the WikiData SPARQL endpoint, but we
would prefer to hike in a place that is sunny. This information is not in WikiData,
but is available through a weather service API called weather.api. This API
implements HTTP requests, so for example to retrieve the weather on Ben Nevis,
the highest mountain in the UK, we can issue a GET request with the IRI:
http://weather.api/request?q=Ben_Nevis
      </p>
      <p>The API responds with a JSON document containing weather information,
say of the form
{"timestamp": "24/10/2017 11:59:07", "temperature": 3,
"description": "clear sky", "coord": {"lat": 56.79, "long": -5.02}}
Therefore, to obtain all Scottish mountains with a favourable weather all we
need to do is call the API for each mountain on our list, keeping only those
records where the weather condition is "clear sky". One can do this manually,
but this quickly become cumbersome, particularly when the number of API calls
is large. Instead, we propose to extend the functionality of SPARQL SERVICE,
allowing it to communicate with JSON APIs such as the weather service above.
For our example we can use the following (extended) query:
SELECT ?x ?l WHERE {
?x wdt:instanceOf wd:mountain . ?x wdt:locatedIn wd:Scotland .
?x rdfs:label ?l .</p>
      <p>SERVICE &lt;http://weather.api/request?q={?l}&gt;{(["description"]) AS (?d)}
FILTER (?d = "clear sky")
}</p>
      <p>The rst part of our query is meant to retrieve the IRI and label of the
mountain in WikiData. The extended SERVICE operator then takes the (instantiated)
URI template where the variable ?l is replaced with the label of the mountain,
and upon executing the API call processes the received JSON document using
an expression ["description"], which extracts from this document the value
under the key description, and binds it to the variable ?d. Finally, we lter
out those locations with undesirable weather conditions.
tu</p>
      <p>
        We proposed a way to implement the overloaded SERVICE operation on top
of any existing SPARQL engine. To do so, we partition each query using this
operator into smaller pieces, and evaluate these using the original engine
whenever possible. The answers given by the engine are extended with the results
provided by the APIs. A full speci cation can be found in [
        <xref ref-type="bibr" rid="ref7">7</xref>
        ].
      </p>
      <p>But can we optimize this queries? We discover that for SERVICE-to-API
queries the bottleneck are the API calls. This is mostly because HTTP requests
are slower that disk access and its something that we cannot control. So if we
want to evaluate queries as e ciently as possible we need to do the least amount
of API calls as possible. Then, can we reformulate query plans to make sure we
are making as few calls as possible?</p>
    </sec>
    <sec id="sec-3">
      <title>A Worst-case optimal algorithm</title>
      <p>
        What we did is to propose an algorithm that is optimal in the worst case. This
algorithm does not make more calls than the number we would need in the worst
case over all graphs and APIs of a given size. For matters of space we will not
explain all the algorithm and the proofs. The details can be found in [
        <xref ref-type="bibr" rid="ref7">7</xref>
        ].
      </p>
      <p>
        Our algorithm is inspired by the optimal plan exhibited in [
        <xref ref-type="bibr" rid="ref1 ref5">1,5</xref>
        ] for
conjunctive queries. To illustrate it, consider the SERVICE-to-API query of the
example1. Note that the query is formed of basic graph patterns and a
SERVICE-toAPI pattern. We treat each basic graph pattern as a relation and each
SERVICEto-API as a relation with access methods (see e.g. [
        <xref ref-type="bibr" rid="ref2 ref4">2,4</xref>
        ]).
      </p>
      <p>Then we can think that a SERVICE-to-API query has the form Q = R1 |&gt;&lt;|
R2 |&gt;&lt;| : : : |&gt;&lt;| Rm. For the sake of presentation we consider that Rj (1 j m)
can represent a basic graph pattern or a SERVICE-to-API pattern where its
attributes are the variables of the basic graph pattern or the input and output
variables of the API. Then, let A1; : : : ; An be an enumeration of all attributes
(variables of SPARQL) involved in Q, in order of their appearance. Starting from
Q, we construct a query Q = n, where the sequence 1; : : : ; n is de ned as:
1 =</p>
      <p>A1 (R1) |&gt;&lt;| : : : |&gt;&lt;| A1 (Rm):
i =</p>
      <p>i 1 |&gt;&lt;| A1;:::;Ai (R1) |&gt;&lt;| : : : |&gt;&lt;| A1;:::;Ai (Rm):</p>
      <p>The idea is to process the query variable by variable. First we obtain the
result of the intersection of all A1 from the BGPs, and then we extend such
BGPs with the values obtained from APIs where their input is the attribute
A1. Then we resolve the join for BGPs with variables A1 and A2 (considering
the results of the previous iteration) and we extend the results with the output
of the APIs with inputs A1 and A2. We continue this process until answer the
query.</p>
      <p>
        Our main result is the following. Take any SERVICE-to-API query Q, and
a database D. Denote by MQ;D the maximum size of the projection of any
relation appearing in Q over a single attribute in the database D. Furthermore,
let 2 (Q;D) be the AGM bound [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ] of the query Q over D, i.e. the maximum
size of the output of Q over any relational database having the same number of
tuples in each relation as D. Then we can prove the following:
Theorem 1. Any feasible join query under access methods Q can be evaluated
over any database instance D using a number of calls in
      </p>
      <p>O(MQ;D
2 (Q;D)):
4</p>
    </sec>
    <sec id="sec-4">
      <title>Experiments</title>
      <p>
        We wanted to give empirical evidence that the worst-case optimal algorithm of
Section 3 is indeed a superior evaluation strategy for executing queries that use
API calls. To construct a benchmark for SERVICE-to-API patterns we
reformulate the queries from the Berlin benchmark [
        <xref ref-type="bibr" rid="ref3">3</xref>
        ] by designating certain patterns
in a query to act as an API call.
Algorithms. We consider three algorithms for SERVICE-to-API patterns: (1)
Vanilla, a naive implementation without optimization; (2) Without duplicates,
the base algorithm that uses caching to avoid doing the same API twice; and
(3) WCO, the worst-case optimal algorithm of Section 3.
      </p>
      <p>Results. The number of API calls done for each of the three versions of our
algorithm are shown in Table 1. As we see, avoiding duplicate calls reduces the
number of calls to some extent, but the best results are obtained when we use
the worst-case optimal algorithm. We also measured the total time taken for the
evaluation of these queries. Query times range from over 8000 seconds to just
0.7 seconds for the Vanilla version, and in average the use of WCO reduces by
40% the running times of the queries.</p>
      <p>Q1 Q2 Q3 Q4 Q5 Q7 Q8 Q10 Q12 AVG</p>
      <p>Vanilla 5332 77 5000 5066 2254 15 1 7 1 0%
W/O Duplicates 4990 3 4990 4990 608 15 1 7 1 20%</p>
      <p>WCO 2971 0 3284 4571 608 13 0 0 1 53%
Table 1. The number of API call per query for each algorithm. WCO plans average
53% reduction in API calls.
5</p>
    </sec>
    <sec id="sec-5">
      <title>Conclusion</title>
      <p>In this paper we propose a way to allow SPARQL queries to connect to HTTP
APIs returning JSON. We give an intuition of the syntax and the semantics of
this extension, discuss how it can be implemented on top of existing SPARQL
engines, show an sketch of a worst-case optimal algorithm for processing these
queries, and show the usefulness of this algorithm in practice. In future work,
we plan to support formats other than JSON, and explore how to support it in
public endpoints.</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          1.
          <string-name>
            <given-names>A.</given-names>
            <surname>Atserias</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Grohe</surname>
          </string-name>
          , and
          <string-name>
            <given-names>D.</given-names>
            <surname>Marx</surname>
          </string-name>
          .
          <article-title>Size bounds and query plans for relational joins</article-title>
          .
          <source>SIAM J. Comput.</source>
          ,
          <volume>42</volume>
          (
          <issue>4</issue>
          ):
          <volume>1737</volume>
          {
          <fpage>1767</fpage>
          ,
          <year>2013</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          2.
          <string-name>
            <given-names>M.</given-names>
            <surname>Benedikt</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Leblay</surname>
          </string-name>
          , and
          <string-name>
            <given-names>E.</given-names>
            <surname>Tsamoura</surname>
          </string-name>
          .
          <article-title>Querying with access patterns and integrity constraints</article-title>
          .
          <source>PVLDB</source>
          ,
          <volume>8</volume>
          (
          <issue>6</issue>
          ):
          <volume>690</volume>
          {
          <fpage>701</fpage>
          ,
          <year>2015</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          3.
          <string-name>
            <given-names>C.</given-names>
            <surname>Bizer</surname>
          </string-name>
          and
          <string-name>
            <surname>A. Schultz.</surname>
          </string-name>
          <article-title>The berlin SPARQL benchmark</article-title>
          .
          <source>Int. J. Semantic Web Inf. Syst.</source>
          ,
          <volume>5</volume>
          (
          <issue>2</issue>
          ):1{
          <fpage>24</fpage>
          ,
          <year>2009</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          4.
          <string-name>
            <given-names>A.</given-names>
            <surname>Cal</surname>
          </string-name>
          and
          <string-name>
            <given-names>D.</given-names>
            <surname>Martinenghi</surname>
          </string-name>
          .
          <article-title>Querying data under access limitations</article-title>
          .
          <source>In ICDE 2008</source>
          , pages
          <fpage>50</fpage>
          {
          <fpage>59</fpage>
          ,
          <year>2008</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          5.
          <string-name>
            <given-names>M.</given-names>
            <surname>Grohe</surname>
          </string-name>
          .
          <article-title>Bounds and algorithms for joins via fractional edge covers</article-title>
          .
          <source>In In Search of Elegance in the Theory and Practice of Computation</source>
          . Springer,
          <year>2013</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          6.
          <string-name>
            <given-names>S.</given-names>
            <surname>Harris</surname>
          </string-name>
          and
          <string-name>
            <given-names>A.</given-names>
            <surname>Seaborne</surname>
          </string-name>
          .
          <source>SPARQL 1</source>
          .
          <article-title>1 query language</article-title>
          .
          <source>W3C</source>
          ,
          <year>2013</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          7.
          <string-name>
            <given-names>M.</given-names>
            <surname>Mosser</surname>
          </string-name>
          ,
          <string-name>
            <given-names>F.</given-names>
            <surname>Pieressa</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J. L.</given-names>
            <surname>Reutter</surname>
          </string-name>
          ,
          <string-name>
            <given-names>A.</given-names>
            <surname>Soto</surname>
          </string-name>
          , and
          <string-name>
            <given-names>D.</given-names>
            <surname>Vrgoc</surname>
          </string-name>
          .
          <article-title>Querying apis with SPARQL: language and worst-case optimal algorithms</article-title>
          .
          <source>In ESWC 2018</source>
          , pages
          <fpage>639</fpage>
          {
          <fpage>654</fpage>
          ,
          <year>2018</year>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>