16.12.3. WebService Interface
REST interface
The Virtuoso Faceted web service provide following REST interface:
Service description:
-
Endpoint: http://<cname>/fct/service for ex. http://lod.openlinksw.com/fct/service
-
HTTP method: POST
-
Content-Type: MUST be 'text/xml'
-
The entity body must be XML document with top element 'query' as described above.
-
The request response namespace MUST be "http://openlinksw.com/services/facets/1.0"
Error conditions:
The all error conditions are reported via 'Error explanation'
Files:
The facet_svc.sql contains web service code and virtual directory mapping, and it uses fct_req.xsl & fct_resp.xsl as request & response filters.
Example:
Using CURL program
curl -H "Content-Type: text/xml" -d @post.xml http://lod.openlinksw.com/fct/service
Where 'post.xml' document contains query document:
<?xml version="1.0"?> <query xmlns="http://openlinksw.com/services/facets/1.0" inference="" same-as=""> <text> Seattle Mariners traveled all the way to Japan to watch</text> <view type="text" limit="20" offset=""/> </query>
Produces following response:
<fct:facets xmlns:fct="http://openlinksw.com/services/facets/1.0/"> <fct:sparql> SELECT distinct ?s1 as ?c1, (bif:search_excerpt (bif:vector ('THE', 'MARINERS', 'WAY', 'SEATTLE', 'WATCH', 'ALL', 'TO', 'JAPAN', 'TRAVELED'), ?o1)) as ?c2 WHERE { ?s1 ?s1textp ?o1 . FILTER (bif:contains (?o1, '(THE AND MARINERS AND WAY AND SEATTLE AND WATCH AND ALL AND TO AND JAPAN AND TRAVELED)')) . } LIMIT 20 OFFSET 0 </fct:sparql> <fct:time>116</fct:time> <fct:complete>yes</fct:complete> <fct:db-activity> 134R rnd 9.488KR seq 0P disk 8.966MB / 602 messages</fct:db-activity> <fct:result> <fct:row> <fct:column datatype="url" shortform="http://bobdupuy.mlbl...ld_baseball__6.html">http://bobdupuy.mlblogs.com/bobdupuy/2006/03/world_baseball__6.html></fct:column> <fct:column /> <fct:column><span class="srch_xerpt">... While Chuck Armstrong president of <b>the</b> <b>Seattle</b> <b>Mariners</b> <b>traveled</b> <b>all</b> <b>the</b> <b>way</b> <b>to</b> <b>Japan</b> <b>to</b> <b>watch</b> Ichiro... for <b>the</b> advancing <b>Japan</b> team last week <b>the</b> star from <b>the</b> <b>Seattle</b> roster so far in Round 1 has without a doubt... leading <b>the</b> Dominican <b>to</b> its...</span></fct:column> </fct:row> <fct:row> <fct:column datatype="url" shortform="http://bobdupuy.mlbl...ld_baseball__6.html">http://bobdupuy.mlblogs.com/bobdupuy/2006/03/world_baseball__6.html></fct:column> <fct:column /> <fct:column><span class="srch_xerpt">Orlando While Chuck Armstrong president of <b>the</b> <b>Seattle</b> <b>Mariners</b> <b>traveled</b> <b>all</b> <b>the</b> <b>way</b> <b>to</b> <b>Japan</b> <b>to</b> <b>watch</b>... perform for <b>the</b> advancing <b>Japan</b> team last week <b>the</b> star from <b>the</b> <b>Seattle</b> roster so far in Round 1 has without...</span></fct:column> </fct:row> </fct:result> </fct:facets>
Virtuoso APIs for Faceted REST services
The Virtuoso APIs for FCT REST services are Virtuoso Stored Procedures that enable faceted browsing over Linked Data hosted in the RDF Quad Store. This also includes Linked Data that is progressively added to the Quad Store via URI de-referencing.
They enable the use Virtuoso's VSP/VSPX technology to produce (X)HTML-based Linked Data explorer pages that are endowed with high-performance (in-process) faceted browsing capability.
You can use this API with Virtuoso SQL calls that provide data to your VSP/VSPX, ASP.NET, PHP, etc., -based interfaces using ODBC, JDBC, ADO.NET, or XMLA connectivity (SPASQL) to Virtuoso.
API Definition
CREATE PROCEDURE fct_exec ( IN tree ANY , IN timeout INT ) { DECLARE start_time, view3, inx, n_rows INT ; DECLARE sqls, msg, qr, qr2, act, query VARCHAR ; DECLARE md, res, results, more ANY ; DECLARE tmp ANY ; DECLARE offs, lim INT ; SET result_timeout = _min ( timeout, ATOI ( registry_get ('fct_timeout_max') ) ) ; offs := xpath_eval ('//query/view/@offset', tree); lim := xpath_eval ('//query/view/@limit', tree); -- db_activity (); results := vector (null, null, null); more := vector (); IF ( xpath_eval ( '//query[@view3="yes"]//view[@type="text"]', tree ) IS NOT NULL ) { more := VECTOR ('classes', 'properties'); } sqls := '00000'; qr := fct_query ( xpath_eval ('//query', tree, 1) ) ; query := qr; -- dbg_obj_print (qr); qr2 := fct_xml_wrap (tree, qr); start_time := msec_time (); dbg_printf('query: %s', qr2); EXEC ( qr2, sqls, msg, vector (), 0, md, res ) ; n_rows := row_count (); act := db_activity (); SET result_timeout = 0; IF ( sqls <> '00000' AND sqls <> 'S1TAT' ) SIGNAL (sqls, msg); IF ( NOT ISARRAY (res) OR 0 = length (res) OR NOT ISARRAY (res[0]) OR 0 = length (res[0]) ) results[0] := xtree_doc ('<result/>'); ELSE results[0] := res[0][0]; inx := 1; FOREACH (VARCHAR tp IN more) DO { tree := XMLUpdate ( tree, '/query/view/@type', tp, '/query/view/@limit', '40', '/query/view/@offset', '0' ) ; qr := fct_query (xpath_eval ('//query', tree, 1)); qr2 := fct_xml_wrap (tree, qr); sqls := '00000'; SET result_timeout = _min ( timeout, ATOI ( registry_get ('fct_timeout_max') ) ) ; EXEC ( qr2, sqls, msg, vector (), 0, md, res ); n_rows := row_count (); act := db_activity (); SET result_timeout = 0; IF ( sqls <> '00000' AND sqls <> 'S1TAT' ) SIGNAL (sqls, msg); IF ( ISARRAY (res) AND LENGTH (res) AND ISARRAY (res[0]) AND LENGTH (res[0]) ) { tmp := res[0][0]; tmp := XMLUpdate (tmp, '/result/@type', tp); results[inx] := tmp; } inx := inx + 1; } res := XMLELEMENT ( "facets", XMLELEMENT ( "sparql", query ), XMLELEMENT ( "time", msec_time () - start_time ), XMLELEMENT ( "complete", CASE WHEN sqls = 'S1TAT' THEN 'no' ELSE 'yes' END ), XMLELEMENT ( "timeout", _min ( timeout * 2, ATOI ( registry_get ( 'fct_timeout_max' ) ) ) ), XMLELEMENT ("db-activity", act), XMLELEMENT ("processed", n_rows), XMLELEMENT ( "view", XMLATTRIBUTES ( offs AS "offset", lim AS "limit" ) ), results[0], results[1], results[2] ); ---- for debugging: --string_to_file ('ret.xml', serialize_to_UTF8_xml (res), -2); -- dbg_obj_print (res); RETURN res; } ;
Example
The following example shows how to use the fct_exec APi in vsp page to perform a "text" search for the word "Mike" assuming this exists in your Virtuoso RDF store (if not amend the query in the fct_example.vsp code sample below to search for text known to exist).
-
The service can be used in the following sample fct_example.vsp:
<?vsp declare txt, reply, tree any; declare timeout int; tree := xtree_doc (' <query> <text>Mike</text> <view type="text"/> </query> '); timeout := 3000; reply := fct_exec (tree, timeout); txt := string_output (); http_value (xslt ('virt://WS.WS.SYS_DAV_RES.RES_FULL_PATH.RES_CONTENT:/DAV/fct_example.xsl', reply, vector ()), null, txt); http (txt); ?>
-
The xsl:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" encoding="ISO-8859-1"/> <xsl:variable name="rowcnt" select="count(/facets/result/row)"/> <xsl:template match="facets"> <div xml:id="res"> <xsl:if test="/facets/complete = 'yes' and /facets/processed = 0 and $rowcnt = 0"> <div class="empty_result"> Nothing found. </div> </xsl:if> <xsl:for-each select="/facets/result"> <xsl:call-template name="render-result"/> </xsl:for-each> </div> <!-- #res --> </xsl:template> <xsl:template name="render-result"> <table class="result" border="1"> <thead> <tr> <th>Entity</th> <th>Title</th> <th>Text excerpt</th> </tr> </thead> <tbody> <xsl:for-each select="row"> <tr> <td class="rnk"> <xsl:for-each select="column[@datatype='trank' or @datatype='erank']"> <xsl:choose> <xsl:when test="./@datatype='trank'">Text Rank:</xsl:when> <xsl:when test="./@datatype='erank'">Entity Rank:</xsl:when> </xsl:choose> <xsl:value-of select="."/> <br/> </xsl:for-each> </td> <xsl:for-each select="column"> <xsl:choose> <xsl:when test="'url' = ./@datatype"> <td> <a> <xsl:attribute name="href">http://lod.openlinksw.com/describe/?url=<xsl:value-of select="urlify (.)"/></xsl:attribute> <xsl:attribute name="title"><xsl:value-of select="."/></xsl:attribute> <xsl:choose> <xsl:when test="'' != ./@shortform"> <xsl:value-of select="./@shortform"/> </xsl:when> <xsl:when test="'erank' = ./@datatype or 'trank' = ./@datatype">rank</xsl:when> <xsl:otherwise> <xsl:value-of select="."/> </xsl:otherwise> </xsl:choose> </a> </td> </xsl:when> <xsl:when test="'erank' = ./@datatype or 'trank' = ./@datatype"/> <xsl:when test="'srch_xerpt' = ./span/@class"> <td> <xsl:value-of select="."/> </td> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:for-each> </tr> </xsl:for-each> </tbody> </table> </xsl:template> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
-
The result of executing the fct_example.vsp should be:
Figure 16.183. Faceted API Example
SOAP interface
The facet web service is also available via SOAP protocol.
The request message contains single element 'query' with syntax explained earlier. Also the SOAPAction HTTP header should be '#query' . After successful evaluation of the query, the service will return a SOAP envelope containing in the Body element single 'facets' element described above.
Example:
This example shows execution of same command as in example for REST interface here it using SOAP:
Request message:
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP:Body> <query xmlns="http://openlinksw.com/services/facets/1.0/" inference="" same-as=""> <text>Seattle Mariners traveled all the way to Japan to watch</text> <view type="text" limit="20" offset="0"/> </query> </SOAP:Body> </SOAP:Envelope>
Response message:
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP:Body> <fct:facets xmlns:fct="http://openlinksw.com/services/facets/1.0/"> <fct:sparql>SELECT distinct ?s1 as ?c1, (bif:search_excerpt (bif:vector ('THE', 'MARINERS', 'WAY', 'SEATTLE', 'WATCH', 'ALL', 'TO', 'JAPAN', 'TRAVELED'), ?o1)) as ?c2 where { ?s1 ?s1textp ?o1 . filter (bif:contains (?o1, '(THE AND MARINERS AND WAY AND SEATTLE AND WATCH AND ALL AND TO AND JAPAN AND TRAVELED)')) . } LIMIT 20 OFFSET 0</fct:sparql> <fct:time>114</fct:time> <fct:complete>yes</fct:complete> <fct:db-activity> 134R rnd 9.488KR seq 0P disk 8.966MB / 602 messages</fct:db-activity> <fct:result> <fct:row> <fct:column datatype="url" shortform="http://bobdupuy.mlbl...ld_baseball__6.html">http://bobdupuy.mlblogs.com/bobdupuy/2006/03/world_baseball__6.html</fct:column> <fct:column/> <fct:column><span class="srch_xerpt">... While Chuck Armstrong president of <b>the</b> <b>Seattle</b> <b>Mariners</b> <b>traveled</b> <b>all</b> <b>the</b> <b>way</b> <b>to</b> <b>Japan</b> <b>to</b> <b>watch</b> Ichiro... for <b>the</b> advancing <b>Japan</b> team last week <b>the</b> star from <b>the</b> <b>Seattle</b> roster so far in Round 1 has without a doubt... leading <b>the</b> Dominican <b>to</b> its...</span></fct:column> </fct:row> <fct:row> <fct:column datatype="url" shortform="http://bobdupuy.mlbl...ld_baseball__6.html">http://bobdupuy.mlblogs.com/bobdupuy/2006/03/world_baseball__6.html</fct:column> <fct:column/> <fct:column><span class="srch_xerpt">Orlando While Chuck Armstrong president of <b>the</b> <b>Seattle</b> <b>Mariners</b> <b>traveled</b> <b>all</b> <b>the</b> <b>way</b> <b>to</b> <b>Japan</b> <b>to</b> <b>watch</b>... perform for <b>the</b> advancing <b>Japan</b> team last week <b>the</b> star from <b>the</b> <b>Seattle</b> roster so far in Round 1 has without...</span></fct:column> </fct:row> </fct:result> </fct:facets> </SOAP:Body> </SOAP:Envelope>