SPARQL queries

Revision as of 18:41, 26 July 2026 by NeoWiki (talk | contribs) (Importing NeoWiki demo data)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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