Jump to content

SPARQL queries: Difference between revisions

From NeoWiki Demo
Content deleted Content added
NeoWiki (talk | contribs)
Importing NeoWiki demo data
 
NeoWiki (talk | contribs)
Importing NeoWiki demo data
 
Line 1: Line 1:
NeoWiki keeps [https://github.com/ProfessionalWiki/NeoWiki/blob/master/docs/operations/installation.md#optional-sparql-graph-stores SPARQL 1.1 graph stores] such as [https://qlever.dev/ QLever] in sync with the wiki's structured data: each page becomes a named graph of RDF triples one per [[RDF and ontology mappings|projection]] the store holds updated on each edit and dropped on deletion. This wiki's store holds the native projection. This page demonstrates the three ways to query it. It is imported only into wikis that have a SPARQL store configured, like the NeoWiki development stack.
NeoWiki keeps a [https://neowiki.ai/docs/operations/installation#optional-sparql-graph-stores SPARQL 1.1 graph store] such as [https://qlever.dev/ QLever] in sync with the wiki's structured data on every edit, so it can be queried live. This page shows the three ways to query it, using the native vocabulary. {{#ifexist:EDM queries|The store also holds the EDM projection: see [[EDM queries]] to query it, or to join across both.}}


== Query with a parser function ==
== Query with a parser function ==


The <code><nowiki>{{#sparql_raw}}</nowiki></code> parser function runs a read-only SPARQL query against the first configured store and returns the raw [https://www.w3.org/TR/sparql11-results-json/ SPARQL JSON results]. Entity, schema, and property IRIs are minted under the wiki's RDF base URI, which defaults to the wiki's own server URL — the examples below write it as <code><nowiki>{{SERVER}}</nowiki></code> so they work on any wiki.
The <code><nowiki>{{#sparql_raw}}</nowiki></code> parser function runs a read-only SPARQL query and returns the raw [https://www.w3.org/TR/sparql11-results-json/ SPARQL JSON results]. IRIs are minted under the wiki's own URL, which the examples write as <code><nowiki>{{SERVER}}</nowiki></code> so they work on any wiki.

Source:


<syntaxhighlight lang="mediawiki">
<syntaxhighlight lang="mediawiki">
Line 15: Line 13:
{{#sparql_raw:SELECT ?museum ?visitors WHERE { ?m <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <{{SERVER}}/schema/Museum> . ?m <http://www.w3.org/2000/01/rdf-schema#label> ?museum . ?m <{{SERVER}}/prop/Annual_visitors> ?visitors } ORDER BY DESC(?visitors) LIMIT 5}}
{{#sparql_raw:SELECT ?museum ?visitors WHERE { ?m <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <{{SERVER}}/schema/Museum> . ?m <http://www.w3.org/2000/01/rdf-schema#label> ?museum . ?m <{{SERVER}}/prop/Annual_visitors> ?visitors } ORDER BY DESC(?visitors) LIMIT 5}}


Each graph is named for the projection and the page it holds — <code>{{SERVER}}/graph/native/page/&lt;pageid&gt;</code> so results can carry provenance, and one store can hold several projections without a page's triples in one overwriting the other's. This query lists people together with the graph each one comes from:
Each page's triples live in their own named graph, <code>{{SERVER}}/graph/native/page/&lt;pageid&gt;</code>, so a result can show which page it came from:


<syntaxhighlight lang="mediawiki">
<syntaxhighlight lang="mediawiki">
Line 27: Line 25:
== Query from Lua ==
== Query from Lua ==


<code>mw.neowiki.sparqlQuery</code> returns the same results document as a Lua table, so Scribunto modules can format it. From [[Module:LuaExample]]:
<code>nw.sparqlQuery</code> returns the same results as a Lua table, so a Scribunto module can format them. From [[Module:LuaExample]]:


<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
Line 60: Line 58:
== Query over REST ==
== Query over REST ==


The same queries work over the wiki's REST API, which returns the results document as JSON:
The same queries work over the REST API, which returns the results as JSON:


<code>POST {{SERVER}}{{SCRIPTPATH}}/rest.php/neowiki/v0/query/sparql</code>
<code>POST {{SERVER}}{{SCRIPTPATH}}/rest.php/neowiki/v0/query/sparql</code>
Line 68: Line 66:
</syntaxhighlight>
</syntaxhighlight>


== Learn more ==
For details, see the [https://github.com/ProfessionalWiki/NeoWiki/blob/master/docs/reference/query-api.md query API], [https://github.com/ProfessionalWiki/NeoWiki/blob/master/docs/reference/parser-functions.md parser function], and [https://github.com/ProfessionalWiki/NeoWiki/blob/master/docs/reference/lua-api.md Lua] documentation. For querying the property graph with Cypher instead, see [[Developers]].

* [https://neowiki.ai/docs/api/query-api Query API reference]
* [https://neowiki.ai/docs/authoring/parser-functions Parser function reference]
* [https://neowiki.ai/docs/authoring/lua-api Lua API reference]
* [[Developers]], to query the property graph with Cypher instead

Latest revision as of 18:41, 26 July 2026

NeoWiki keeps a SPARQL 1.1 graph store such as QLever in sync with the wiki's structured data on every edit, so it can be queried live. This page shows the three ways to query it, using the native vocabulary.

Query with a parser function

The {{#sparql_raw}} parser function runs a read-only SPARQL query and returns the raw SPARQL JSON results. IRIs are minted under the wiki's own URL, which the examples write as {{SERVER}} so they work on any wiki.

{{#sparql_raw:SELECT ?museum ?visitors WHERE { ?m <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <{{SERVER}}/schema/Museum> . ?m <http://www.w3.org/2000/01/rdf-schema#label> ?museum . ?m <{{SERVER}}/prop/Annual_visitors> ?visitors } ORDER BY DESC(?visitors) LIMIT 5}}

Result:

{
    "head": {
        "vars": [
            "museum",
            "visitors"
        ]
    },
    "results": {
        "bindings": [
            {
                "museum": {
                    "type": "literal",
                    "value": "Mus\u00e9e d'Orsay"
                },
                "visitors": {
                    "datatype": "http://www.w3.org/2001/XMLSchema#int",
                    "type": "literal",
                    "value": "3270000"
                }
            },
            {
                "museum": {
                    "type": "literal",
                    "value": "Museo del Prado"
                },
                "visitors": {
                    "datatype": "http://www.w3.org/2001/XMLSchema#int",
                    "type": "literal",
                    "value": "3200000"
                }
            },
            {
                "museum": {
                    "type": "literal",
                    "value": "Rijksmuseum"
                },
                "visitors": {
                    "datatype": "http://www.w3.org/2001/XMLSchema#int",
                    "type": "literal",
                    "value": "2700000"
                }
            },
            {
                "museum": {
                    "type": "literal",
                    "value": "Kunsthistorisches Museum"
                },
                "visitors": {
                    "datatype": "http://www.w3.org/2001/XMLSchema#int",
                    "type": "literal",
                    "value": "1800000"
                }
            }
        ]
    },
    "meta": {
        "query-time-ms": 1,
        "result-size-total": 4
    }
}

Each page's triples live in their own named graph, https://neowiki.dev/graph/native/page/<pageid>, so a result can show which page it came from:

{{#sparql_raw:SELECT ?graph ?person WHERE { GRAPH ?graph { ?p <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <{{SERVER}}/schema/Person> . ?p <http://www.w3.org/2000/01/rdf-schema#label> ?person } } ORDER BY ?person LIMIT 5}}

Result:

{
    "head": {
        "vars": [
            "graph",
            "person"
        ]
    },
    "results": {
        "bindings": [
            {
                "graph": {
                    "type": "uri",
                    "value": "https://neowiki.dev/graph/native/page/168"
                },
                "person": {
                    "type": "literal",
                    "value": "Anna Magdalena Bach"
                }
            },
            {
                "graph": {
                    "type": "uri",
                    "value": "https://neowiki.dev/graph/native/page/164"
                },
                "person": {
                    "type": "literal",
                    "value": "Carl Philipp Emanuel Bach"
                }
            },
            {
                "graph": {
                    "type": "uri",
                    "value": "https://neowiki.dev/graph/native/page/165"
                },
                "person": {
                    "type": "literal",
                    "value": "Johann Ambrosius Bach"
                }
            },
            {
                "graph": {
                    "type": "uri",
                    "value": "https://neowiki.dev/graph/native/page/170"
                },
                "person": {
                    "type": "literal",
                    "value": "Johann Christian Bach"
                }
            },
            {
                "graph": {
                    "type": "uri",
                    "value": "https://neowiki.dev/graph/native/page/175"
                },
                "person": {
                    "type": "literal",
                    "value": "Johann Sebastian Bach"
                }
            }
        ]
    },
    "meta": {
        "query-time-ms": 1,
        "result-size-total": 5
    }
}

Query from Lua

nw.sparqlQuery returns the same results as a Lua table, so a Scribunto module can format them. From Module:LuaExample:

function p.largestMuseums( frame )
	local base = mw.site.server
	local result = nw.sparqlQuery(
		'SELECT ?label ?visitors WHERE { ' ..
		'?m <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <' .. base .. '/schema/Museum> . ' ..
		'?m <http://www.w3.org/2000/01/rdf-schema#label> ?label . ' ..
		'?m <' .. base .. '/prop/Annual_visitors> ?visitors ' ..
		'} ORDER BY DESC(?visitors) LIMIT 3'
	)

	local list = {}
	for _, binding in ipairs( result.results.bindings ) do
		list[#list + 1] = '* ' .. binding.label.value .. ' (' .. binding.visitors.value .. ' visitors)'
	end
	return table.concat( list, '\n' )
end

Invoke it from wikitext:

{{#invoke:LuaExample|largestMuseums}}

Result:

  • Musée d'Orsay (3270000 visitors)
  • Museo del Prado (3200000 visitors)
  • Rijksmuseum (2700000 visitors)

Query over REST

The same queries work over the REST API, which returns the results as JSON:

POST https://neowiki.dev/w/rest.php/neowiki/v0/query/sparql

{ "query": "SELECT ?label WHERE { ?s <http://www.w3.org/2000/01/rdf-schema#label> ?label } LIMIT 5" }

Learn more