-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #134 from RDFLib/edmond/feat/vocabs-api
Add new vocabs API to load large vocabularies incrementally
- Loading branch information
Showing
37 changed files
with
1,637 additions
and
424 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
from rdflib import Graph, URIRef, BNode | ||
|
||
|
||
def get_bnode_depth( | ||
graph: Graph, node: URIRef | BNode = None, depth: int = 0, seen: list[BNode] = None | ||
) -> int: | ||
"""Get the max blank node depth of the node in the graph. | ||
This is a recursive function. | ||
>>> graph = Graph().parse(...) | ||
>>> depth = get_bnode_depth(graph, URIRef("node-name")) | ||
""" | ||
if seen is None: | ||
seen = [] | ||
|
||
if isinstance(node, BNode) or depth == 0: | ||
for o in graph.objects(node, None): | ||
if isinstance(o, BNode) and o not in seen: | ||
seen.append(o) | ||
depth = get_bnode_depth(graph, o, depth + 1, seen) | ||
|
||
return depth |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
from textwrap import dedent | ||
|
||
from jinja2 import Template | ||
|
||
|
||
def object_inbound_query(iri: str, predicate: str) -> str: | ||
query = Template( | ||
""" | ||
SELECT (COUNT(?iri) as ?count) | ||
WHERE { | ||
BIND(<{{ iri }}> as ?iri) | ||
?other <{{ predicate }}> ?iri . | ||
} | ||
""" | ||
).render(iri=iri, predicate=predicate) | ||
|
||
return dedent(query) | ||
|
||
|
||
def object_outbound_query(iri: str, predicate: str) -> str: | ||
query = Template( | ||
""" | ||
SELECT (COUNT(?iri) as ?count) | ||
WHERE { | ||
BIND(<{{ iri }}> as ?iri) | ||
?iri <{{ predicate }}> ?other . | ||
} | ||
""" | ||
).render(iri=iri, predicate=predicate) | ||
|
||
return dedent(query) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
from textwrap import dedent | ||
|
||
from jinja2 import Template | ||
|
||
|
||
def get_concept_scheme_query(iri: str, bnode_depth: int) -> str: | ||
query = Template( | ||
""" | ||
PREFIX prez: <https://prez.dev/> | ||
PREFIX skos: <http://www.w3.org/2004/02/skos/core#> | ||
CONSTRUCT { | ||
?iri ?p ?o . | ||
{% if bnode_depth > 0 +%} | ||
?iri ?p0 ?o0 . | ||
{% endif %} | ||
{% for i in range(bnode_depth) %} | ||
?o{{ i }} ?p{{ i + 1 }} ?o{{ i + 1 }} . | ||
{% endfor %} | ||
?iri prez:childrenCount ?childrenCount . | ||
} | ||
WHERE { | ||
BIND(<{{ iri }}> as ?iri) | ||
?iri ?p ?o . | ||
FILTER (?p != skos:hasTopConcept) | ||
{ | ||
SELECT (COUNT(?topConcept) AS ?childrenCount) | ||
WHERE { | ||
BIND(<{{ iri }}> as ?iri) | ||
?iri skos:hasTopConcept ?topConcept . | ||
} | ||
} | ||
{% if bnode_depth > 0 %} | ||
?iri ?p0 ?o0 . | ||
{% endif %} | ||
{% for i in range(bnode_depth) %} | ||
?o{{ i }} ?p{{ i + 1 }} ?o{{ i + 1 }} . | ||
FILTER (isBlank(?o0)) | ||
{% endfor %} | ||
} | ||
""" | ||
).render(iri=iri, bnode_depth=bnode_depth) | ||
|
||
return dedent(query) | ||
|
||
|
||
def get_concept_scheme_top_concepts_query(iri: str, page: int, per_page: int) -> str: | ||
query = Template( | ||
""" | ||
PREFIX prez: <https://prez.dev/> | ||
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> | ||
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> | ||
PREFIX skos: <http://www.w3.org/2004/02/skos/core#> | ||
CONSTRUCT { | ||
?concept skos:prefLabel ?label . | ||
?concept prez:childrenCount ?narrowerChildrenCount . | ||
?iri prez:childrenCount ?childrenCount . | ||
?iri skos:hasTopConcept ?concept . | ||
} | ||
WHERE { | ||
BIND(<{{ iri }}> as ?iri) | ||
?iri skos:hasTopConcept ?concept . | ||
?concept skos:prefLabel ?label . | ||
{ | ||
SELECT (COUNT(?childConcept) AS ?childrenCount) | ||
WHERE { | ||
BIND(<{{ iri }}> as ?iri) | ||
?iri skos:hasTopConcept ?childConcept . | ||
} | ||
} | ||
{ | ||
SELECT ?concept ?label (COUNT(?narrowerConcept) AS ?narrowerChildrenCount) | ||
WHERE { | ||
BIND(<{{ iri }}> as ?iri) | ||
?iri skos:hasTopConcept ?concept . | ||
?concept skos:prefLabel ?label . | ||
OPTIONAL { | ||
?narrowerConcept skos:broader ?concept . | ||
} | ||
} | ||
GROUP BY ?concept ?label | ||
ORDER BY str(?label) | ||
LIMIT {{ limit }} | ||
OFFSET {{ offset }} | ||
} | ||
} | ||
""" | ||
).render(iri=iri, limit=per_page, offset=(page - 1) * per_page) | ||
|
||
return dedent(query) | ||
|
||
|
||
def get_concept_narrowers_query(iri: str, page: int, per_page: int) -> str: | ||
query = Template( | ||
""" | ||
PREFIX prez: <https://prez.dev/> | ||
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> | ||
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> | ||
PREFIX skos: <http://www.w3.org/2004/02/skos/core#> | ||
CONSTRUCT { | ||
?concept skos:prefLabel ?label . | ||
?concept prez:childrenCount ?narrowerChildrenCount . | ||
?iri prez:childrenCount ?childrenCount . | ||
?iri skos:narrower ?concept . | ||
} | ||
WHERE { | ||
BIND(<{{ iri }}> as ?iri) | ||
?concept skos:broader ?iri . | ||
?concept skos:prefLabel ?label . | ||
{ | ||
SELECT (COUNT(?childConcept) AS ?childrenCount) | ||
WHERE { | ||
BIND(<{{ iri }}> as ?iri) | ||
?childConcept skos:broader ?iri . | ||
} | ||
} | ||
{ | ||
SELECT ?concept ?label (COUNT(?narrowerConcept) AS ?narrowerChildrenCount) | ||
WHERE { | ||
BIND(<{{ iri }}> as ?iri) | ||
?concept skos:broader ?iri . | ||
?concept skos:prefLabel ?label . | ||
OPTIONAL { | ||
?narrowerConcept skos:broader ?concept . | ||
} | ||
} | ||
GROUP BY ?concept ?label | ||
ORDER BY str(?label) | ||
LIMIT {{ limit }} | ||
OFFSET {{ offset }} | ||
} | ||
} | ||
""" | ||
).render(iri=iri, limit=per_page, offset=(page - 1) * per_page) | ||
|
||
return dedent(query) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
from fastapi.responses import StreamingResponse | ||
|
||
|
||
class StreamingTurtleResponse(StreamingResponse): | ||
media_type = "text/turtle" | ||
|
||
def render(self, content: str) -> bytes: | ||
return content.encode("utf-8") | ||
|
||
|
||
class StreamingTurtleAnnotatedResponse(StreamingTurtleResponse): | ||
media_type = "text/anot+turtle" |
Oops, something went wrong.