{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "chem-bla-ics",
  "description": "Chemblaics (pronounced chem-bla-ics) is the science that uses open science and computers to solve problems in chemistry, biochemistry and related fields.",
  "home_page_url": "https://chem-bla-ics.linkedchemistry.info/",
  "feed_url": "https://chem-bla-ics.linkedchemistry.info/2016/07/02/two-apache-jena-sparql-query.json",
  "icon": "https://chem-bla-ics.linkedchemistry.info/assets/images/chem-bla-ics_logo.png",
  "language": "en",
  "authors": [
    {
      "name": "Egon Willighagen",
      "url": "https://orcid.org/0000-0001-7542-0286",
      "_orcid": "0000-0001-7542-0286"
    }
  ],
  "items": [

    {
      "id": "https://doi.org/10.59350/nwnd6-hj737",
      "url": "https://chem-bla-ics.linkedchemistry.info/2016/07/02/two-apache-jena-sparql-query.html",
      "title": "Two Apache Jena SPARQL query performance observations",
      "content_html": "<p><span style=\"width: 50%; display: block; margin-left: auto; margin-right: auto; float: right\">\n<img src=\"/assets/images/jenaSlow.png\" />\n</span></p>\n\n<p>Doing searches in RDF stores is commonly done with SPARQL queries. I have been using this with <a href=\"http://chem-bla-ics.blogspot.nl/2016/06/new-paper-using-semantic-web-for-rapid.html\">the semantic web translation of WikiPathways</a>\nby <a href=\"https://twitter.com/andrawaag\">Andra</a> to find common content issues, though sometimes combined with some additional Java code.\nFor example, find <a href=\"http://www.ncbi.nlm.nih.gov/pubmed\">PubMed</a> identifiers that are not numbers.</p>\n\n<p>Based on <a href=\"http://orcid.org/0000-0003-3477-7443\">Ryan</a>’s work on interactions, a more complex curation query I\nrecently wrote in reply to issues that <a href=\"https://twitter.com/xanderpico\">Alex</a> ran into with converting pathways to\nBioPax, is to find interactions that convert a gene to another gene. Such occurred in <a href=\"http://wikipathways.org/\">WikiPathways</a>\nbecause graphically you do not see the difference. I originally had this query:</p>\n\n<div class=\"language-sparql highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">SELECT</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"nb\">str</span><span class=\"p\">(</span><span class=\"nv\">?organismName</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">as</span><span class=\"w\"> </span><span class=\"nv\">?organism</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"nv\">?page</span><span class=\"w\">\n       </span><span class=\"nv\">?gene1</span><span class=\"w\"> </span><span class=\"nv\">?gene2</span><span class=\"w\"> </span><span class=\"nv\">?interaction</span><span class=\"w\">\n</span><span class=\"k\">WHERE</span><span class=\"w\"> </span><span class=\"p\">{</span><span class=\"w\">\n  </span><span class=\"nv\">?gene1</span><span class=\"w\"> </span><span class=\"k\">a</span><span class=\"w\"> </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">GeneProduct</span><span class=\"w\"> </span><span class=\"p\">.</span><span class=\"w\">\n  </span><span class=\"nv\">?gene2</span><span class=\"w\"> </span><span class=\"k\">a</span><span class=\"w\"> </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">GeneProduct</span><span class=\"w\"> </span><span class=\"p\">.</span><span class=\"w\">\n  </span><span class=\"nv\">?interaction</span><span class=\"w\"> </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">source</span><span class=\"w\"> </span><span class=\"nv\">?gene1</span><span class=\"w\"> </span><span class=\"p\">;</span><span class=\"w\">\n    </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">target</span><span class=\"w\"> </span><span class=\"nv\">?gene2</span><span class=\"w\"> </span><span class=\"p\">;</span><span class=\"w\">\n    </span><span class=\"k\">a</span><span class=\"w\"> </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">Conversion</span><span class=\"w\"> </span><span class=\"p\">;</span><span class=\"w\">\n    </span><span class=\"nn\">dcterms</span><span class=\"o\">:</span><span class=\"ss\">isPartOf</span><span class=\"w\"> </span><span class=\"nv\">?pathway</span><span class=\"w\"> </span><span class=\"p\">.</span><span class=\"w\">\n  </span><span class=\"nv\">?pathway</span><span class=\"w\"> </span><span class=\"nn\">foaf</span><span class=\"o\">:</span><span class=\"ss\">page</span><span class=\"w\"> </span><span class=\"nv\">?page</span><span class=\"w\"> </span><span class=\"p\">;</span><span class=\"w\">\n    </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">organismName</span><span class=\"w\"> </span><span class=\"nv\">?organismName</span><span class=\"w\"> </span><span class=\"p\">.</span><span class=\"w\">\n</span><span class=\"p\">}</span><span class=\"w\"> </span><span class=\"k\">ORDER</span><span class=\"w\"> </span><span class=\"k\">BY</span><span class=\"w\"> </span><span class=\"k\">ASC</span><span class=\"p\">(</span><span class=\"nv\">?organism</span><span class=\"p\">)</span><span class=\"w\">\n</span></code></pre></div></div>\n\n<p>This query properly found all gene-gene conversions to be fixed. However, it was also horribly slow with my\n<a href=\"http://junit.org/\">JUnit</a>/<a href=\"https://jena.apache.org/\">Apache Jena</a> set up. The queries runs very efficiently on <a href=\"http://sparql.wikipathways.org/\">the Virtuoso-based SPARQL end point</a>.\nI had been trying to speed it up in the past, but without much success. Instead, I ended up batching the\ntesting on our Jenkins instance. But this got a bit silly, with at some point subsets of less than 100 pathways.</p>\n\n<h2 id=\"observation-1\">Observation #1</h2>\n\n<p>So, I <a href=\"https://twitter.com/egonwillighagen/status/748817658758344704\">turned to twitter</a>, and quite soon got\n<a href=\"https://twitter.com/xbib/status/748818534457716736\">three</a> <a href=\"https://twitter.com/jervenbolleman/status/748820145028550656\">useful</a>\n<a href=\"https://twitter.com/soilandreyes/status/748891148182257664\">leads</a>. The first two suggestions did not help, but helped me rule out the problem.\nOf course, there is literature about optimizing, like this recent paper by Antonis (doi:<a href=\"http://doi.org/10.1016/j.websem.2014.11.003\">10.1016/j.websem.2014.11.003</a>),\nbut I haven’t been able to convert this knowledge into practical steps either. After ruling out these options (though I kept the\n<code class=\"language-plaintext highlighter-rouge\">sameTerm()</code> suggestion), and realized it had to be the first two triples with the variables <code class=\"language-plaintext highlighter-rouge\">?gene1</code> and <code class=\"language-plaintext highlighter-rouge\">?gene2</code>. So,\n<a href=\"https://github.com/BiGCAT-UM/WikiPathwaysCurator/commit/b8283419b252bd8525631d5035d086a15d0773e0\">I tried using <em>FILTER</em> there too</a>,\nresulting with this query:</p>\n\n<div class=\"language-sparql highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">WHERE</span><span class=\"w\"> </span><span class=\"p\">{</span><span class=\"w\">\n  </span><span class=\"nv\">?interaction</span><span class=\"w\"> </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">source</span><span class=\"w\"> </span><span class=\"nv\">?gene1</span><span class=\"w\"> </span><span class=\"p\">;</span><span class=\"w\">\n    </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">target</span><span class=\"w\"> </span><span class=\"nv\">?gene2</span><span class=\"w\"> </span><span class=\"p\">;</span><span class=\"w\">\n    </span><span class=\"k\">a</span><span class=\"w\"> </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">Conversion</span><span class=\"w\"> </span><span class=\"p\">;</span><span class=\"w\">\n    </span><span class=\"nn\">dcterms</span><span class=\"o\">:</span><span class=\"ss\">isPartOf</span><span class=\"w\"> </span><span class=\"nv\">?pathway</span><span class=\"w\"> </span><span class=\"p\">.</span><span class=\"w\">\n  </span><span class=\"nv\">?pathway</span><span class=\"w\"> </span><span class=\"nn\">foaf</span><span class=\"o\">:</span><span class=\"ss\">page</span><span class=\"w\"> </span><span class=\"nv\">?page</span><span class=\"w\"> </span><span class=\"p\">;</span><span class=\"w\">\n    </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">organismName</span><span class=\"w\"> </span><span class=\"nv\">?organismName</span><span class=\"w\"> </span><span class=\"p\">.</span><span class=\"w\">\n  </span><span class=\"k\">FILTER</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"o\">!</span><span class=\"nb\">sameTerm</span><span class=\"p\">(</span><span class=\"nv\">?gene1</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"nv\">?gene2</span><span class=\"p\">))</span><span class=\"w\">\n  </span><span class=\"k\">FILTER</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"nv\">?gene1</span><span class=\"w\"> </span><span class=\"k\">a</span><span class=\"w\"> </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">GeneProduct</span><span class=\"p\">)</span><span class=\"w\">\n  </span><span class=\"k\">FILTER</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"nv\">?gene2</span><span class=\"w\"> </span><span class=\"k\">a</span><span class=\"w\"> </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">GeneProduct</span><span class=\"p\">)</span><span class=\"w\">\n</span><span class=\"p\">}</span><span class=\"w\"> </span><span class=\"k\">ORDER</span><span class=\"w\"> </span><span class=\"k\">BY</span><span class=\"w\"> </span><span class=\"k\">ASC</span><span class=\"p\">(</span><span class=\"nv\">?organism</span><span class=\"p\">)</span><span class=\"w\">\n</span></code></pre></div></div>\n\n<p>That did it! The time to run a query halved. Not so surprising, in retrospect, but it all depends on the SPARQL engine:\nwhich parts does it run first. Apparently, Jena’s SPARQL engine starts at the top. This seems to be confirmed by\n<a href=\"https://twitter.com/soilandreyes/status/748891148182257664\">the third comment I got</a>. However, I always understood\nengine can also start at the bottom.</p>\n\n<h2 id=\"observation-2\">Observation #2</h2>\n\n<p>But that’s not all. This speed up made me wonder something else. The problem clearly seems to engine approach to run\nparts of the query. So, what if I remove further choices in what to run first? That leads me to\n<a href=\"https://twitter.com/egonwillighagen/status/748844395701506048\">a second observation</a>. It helps significantly if you\nreduce the number of subgraphs it should later “merge”. Instead, if possible, use\n<a href=\"https://www.w3.org/TR/sparql11-query/#propertypaths\">property paths</a>. That again, about halved the runtime of the query.\nI ended up with the below query, which, obviously, no longer give me access to the pathway resources, but I can live\nwith that:</p>\n\n<div class=\"language-sparql highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">WHERE</span><span class=\"w\"> </span><span class=\"p\">{</span><span class=\"w\">\n  </span><span class=\"nv\">?interaction</span><span class=\"w\"> </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">source</span><span class=\"w\"> </span><span class=\"nv\">?gene1</span><span class=\"w\"> </span><span class=\"p\">;</span><span class=\"w\">\n    </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">target</span><span class=\"w\"> </span><span class=\"nv\">?gene2</span><span class=\"w\"> </span><span class=\"p\">;</span><span class=\"w\">\n    </span><span class=\"k\">a</span><span class=\"w\"> </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">Conversion</span><span class=\"w\"> </span><span class=\"p\">;</span><span class=\"w\">\n    </span><span class=\"nn\">dcterms</span><span class=\"o\">:</span><span class=\"ss\">isPartOf</span><span class=\"o\">/</span><span class=\"nn\">foaf</span><span class=\"o\">:</span><span class=\"ss\">page</span><span class=\"w\"> </span><span class=\"nv\">?pathway</span><span class=\"w\"> </span><span class=\"p\">;</span><span class=\"w\">\n    </span><span class=\"nn\">dcterms</span><span class=\"o\">:</span><span class=\"ss\">isPartOf</span><span class=\"o\">/</span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">organismName</span><span class=\"w\"> </span><span class=\"nv\">?organismName</span><span class=\"w\"> </span><span class=\"p\">.</span><span class=\"w\">\n  </span><span class=\"k\">FILTER</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"o\">!</span><span class=\"nb\">sameTerm</span><span class=\"p\">(</span><span class=\"nv\">?gene1</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"nv\">?gene2</span><span class=\"p\">))</span><span class=\"w\">\n  </span><span class=\"k\">FILTER</span><span class=\"w\"> </span><span class=\"k\">EXISTS</span><span class=\"w\"> </span><span class=\"p\">{</span><span class=\"nv\">?gene1</span><span class=\"w\"> </span><span class=\"k\">a</span><span class=\"w\"> </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">GeneProduct</span><span class=\"p\">}</span><span class=\"w\">\n  </span><span class=\"k\">FILTER</span><span class=\"w\"> </span><span class=\"k\">EXISTS</span><span class=\"w\"> </span><span class=\"p\">{</span><span class=\"nv\">?gene2</span><span class=\"w\"> </span><span class=\"k\">a</span><span class=\"w\"> </span><span class=\"nn\">wp</span><span class=\"o\">:</span><span class=\"ss\">GeneProduct</span><span class=\"p\">}</span><span class=\"w\">\n</span><span class=\"p\">}</span><span class=\"w\"> </span><span class=\"k\">ORDER</span><span class=\"w\"> </span><span class=\"k\">BY</span><span class=\"w\"> </span><span class=\"k\">ASC</span><span class=\"p\">(</span><span class=\"nv\">?organism</span><span class=\"p\">)</span><span class=\"w\">\n</span></code></pre></div></div>\n\n<p>I’m hoping these two observations may help other with using Apache Jena with unit and integrated testing of RDF generation too.</p>\n\n<h4>References</h4>\n<div class=\"csl-bib-body\">\n    <div class=\"csl-entry\">Loizou, A., Angles, R., &#38; Groth, P. (2015). On the formulation of performant SPARQL queries. <i>Journal of Web Semantics</i>, <i>31</i>, 1–26. https://doi.org/10.1016/j.websem.2014.11.003 <a href=\"https://doi.org/10.1016/j.websem.2014.11.003\">CrossRef</a> <a href=\"https://qlever.scholia.wiki/doi/10.1016/j.websem.2014.11.003\">Scholia</a></div>\n  </div>",
      "summary": "",
      "image": "https://chem-bla-ics.linkedchemistry.info/assets/images/jenaSlow.png",
      "date_published": "2016-07-02T00:00:00+00:00",
      "date_modified": "2016-07-02T00:00:00+00:00",
      "tags": ["curation","wikipathways","sparql","rdf"],
      "_references": [
        
          
          
            { "url": "https://doi.org/10.1016/j.websem.2014.11.003", "doi": "10.1016/j.websem.2014.11.003"
             }
            
          
        ],
      
      
      
      
      
      
        "authors": [ { "name": "Egon Willighagen", "url": "https://orcid.org/0000-0001-7542-0286" } ]
      
    }

  ]
}
