Skip to content

Functionality for mapping SPARQL query result sets to Pydantic models

License

Notifications You must be signed in to change notification settings

acdh-oeaw/rdfproxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

83 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RDFProxy

tests coverage License: GPL v3 Ruff

Functionality for mapping SPARQL result sets to Pydantic models.

SPARQLModelAdapter

The rdfproxy.SPARQLModelAdapter class allows to run a query against an endpoint and map a flat SPARQL query result set to a potentially nested Pydantic model. The result is returned as a Page object.

The following example query

select *
where {
    values (?gnd ?authorName ?educatedAt ?workName ?work ?viaf) {
        (119359464 'Schindel' UNDEF 'Gebürtig' <http://www.wikidata.org/entity/Q1497409> UNDEF)
        (115612815 'Geiger' 'University of Vienna' 'Der alte König in seinem Exil' <http://www.wikidata.org/entity/Q15805238> 299260555)
        (115612815 'Geiger' 'University of Vienna' 'Der alte König in seinem Exil' <http://www.wikidata.org/entity/Q15805238> 6762154387354230970008)
        (115612815 'Geiger' 'University of Vienna' 'Unter der Drachenwand' <http://www.wikidata.org/entity/Q58038819> 2277151717053313900002)
        (1136992030 'Edelbauer' 'University of Vienna' 'Das flüssige Land' <http://www.wikidata.org/entity/Q100266054> UNDEF)
        (1136992030 'Edelbauer' 'University of Applied Arts Vienna' 'Das flüssige Land' <http://www.wikidata.org/entity/Q100266054> UNDEF)
    }
}

retrieves the result set:

gnd nameLabel educated_atLabel work_name work viaf
119359464 Schindel Gebürtig http://www.wikidata.org/entity/Q1497409
115612815 Geiger University of Vienna Der alte König in seinem Exil http://www.wikidata.org/entity/Q15805238 299260555
115612815 Geiger University of Vienna Der alte König in seinem Exil http://www.wikidata.org/entity/Q15805238 6762154387354230970008
115612815 Geiger University of Vienna Unter der Drachenwand http://www.wikidata.org/entity/Q58038819 2277151717053313900002
1136992030 Edelbauer University of Vienna Das flüssige Land http://www.wikidata.org/entity/Q100266054
1136992030 Edelbauer University of Applied Arts Vienna Das flüssige Land http://www.wikidata.org/entity/Q100266054

The result set can be mapped to a nested Pydantic model like so:

from typing import Annotated

from fastapi import FastAPI, Query
from pydantic import BaseModel
from rdfproxy import ConfigDict, Page, QueryParameters, SPARQLBinding, SPARQLModelAdapter

class Work(BaseModel):
    model_config = ConfigDict(group_by="name")

    name: Annotated[str, SPARQLBinding("workName")]
    viafs: Annotated[list[str], SPARQLBinding("viaf")]

class Author(BaseModel):
    model_config = ConfigDict(group_by="surname")

    gnd: str
    surname: Annotated[str, SPARQLBinding("authorName")]
    works: list[Work]
    education: Annotated[list[str], SPARQLBinding("educatedAt")]

adapter = SPARQLModelAdapter(
    target="https://query.wikidata.org/bigdata/namespace/wdq/sparql",
    query=query,
    model=Author,
)

The SPARQLModelAdapter.query method runs the query and constructs a Page object which can then be served over a FastAPI route:

app = FastAPI()

@app.get("/")
def base_route(query_parameters: Annotated[QueryParameters, Query()]) -> Page[Author]:
    return adapter.query(query_parameters)

This results in the following JSON output:

{
   "items":[
      {
         "gnd":"119359464",
         "surname":"Schindel",
         "works":[
            {
               "name":"Gebürtig",
               "viafs":[
                  
               ]
            }
         ],
         "education":[
            
         ]
      },
      {
         "gnd":"115612815",
         "surname":"Geiger",
         "works":[
            {
               "name":"Der alte König in seinem Exil",
               "viafs":[
                  "299260555",
                  "6762154387354230970008"
               ]
            },
            {
               "name":"Unter der Drachenwand",
               "viafs":[
                  "2277151717053313900002"
               ]
            }
         ],
         "education":[
            "University of Vienna"
         ]
      },
      {
         "gnd":"1136992030",
         "surname":"Edelbauer",
         "works":[
            {
               "name":"Das flüssige Land",
               "viafs":[
                  
               ]
            }
         ],
         "education":[
            "University of Vienna",
            "University of Applied Arts Vienna"
         ]
      }
   ],
   "page":1,
   "size":100,
   "total":3,
   "pages":1
}