Fix RDF visualization: correct SPARQL namespaces and show all node types
- Update SPARQL CONSTRUCT query to use correct ontology namespaces: - hc: https://w3id.org/heritage/custodian/ (was nde) - Use nde:Custodian type (was crm:E39_Actor) - Use schema:location + geo:lat/long (was crm predicates) - Remove LIMIT 500 clause to fetch all results - Show all node types by default instead of random single type - Fixes issue where Knowledge Graph showed incomplete/random data
This commit is contained in:
parent
e0dd847491
commit
5fe692296d
1 changed files with 63 additions and 88 deletions
|
|
@ -490,99 +490,82 @@ export function Visualize() {
|
|||
? (import.meta.env.VITE_SPARQL_ENDPOINT || 'http://localhost:7878/query')
|
||||
: '/query'; // Always use relative URL in production
|
||||
|
||||
// SPARQL query aligned with actual RDF generated by oxigraph_sync.py and oxigraph_person_sync.py
|
||||
// Namespaces match the Python sync scripts:
|
||||
// - nde: <https://nde.nl/ontology/hc/class/> for Custodian type
|
||||
// - hc: <https://w3id.org/heritage/custodian/> for ghcid, isil predicates
|
||||
// - hp: <https://w3id.org/heritage/person/> for person URIs
|
||||
const constructQuery = `
|
||||
PREFIX crm: <http://www.cidoc-crm.org/cidoc-crm/>
|
||||
PREFIX hc: <https://nde.nl/ontology/hc/>
|
||||
PREFIX hcc: <https://nde.nl/ontology/hc/class/>
|
||||
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#>
|
||||
PREFIX schema: <http://schema.org/>
|
||||
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
|
||||
PREFIX dcterms: <http://purl.org/dc/terms/>
|
||||
PREFIX owl: <http://www.w3.org/2002/07/owl#>
|
||||
PREFIX prov: <http://www.w3.org/ns/prov#>
|
||||
|
||||
PREFIX org: <http://www.w3.org/ns/org#>
|
||||
PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>
|
||||
PREFIX cidoc: <http://www.cidoc-crm.org/cidoc-crm/>
|
||||
PREFIX nde: <https://nde.nl/ontology/hc/class/>
|
||||
PREFIX hc: <https://w3id.org/heritage/custodian/>
|
||||
PREFIX hp: <https://w3id.org/heritage/person/>
|
||||
|
||||
CONSTRUCT {
|
||||
# Core custodian data
|
||||
?custodian a crm:E39_Actor ;
|
||||
skos:prefLabel ?label ;
|
||||
skos:altLabel ?altLabel ;
|
||||
hc:custodian_type ?type ;
|
||||
dcterms:identifier ?dcId .
|
||||
# Custodians - core data
|
||||
?custodian a nde:Custodian ;
|
||||
rdfs:label ?label ;
|
||||
skos:prefLabel ?prefLabel ;
|
||||
schema:name ?name ;
|
||||
hc:ghcid ?ghcid ;
|
||||
hc:isil ?isil ;
|
||||
schema:url ?website ;
|
||||
foaf:homepage ?homepage ;
|
||||
owl:sameAs ?wikidata .
|
||||
|
||||
# Location with coordinates
|
||||
?custodian crm:P53_has_former_or_current_location ?place .
|
||||
?place a schema:Place ;
|
||||
schema:latitude ?lat ;
|
||||
schema:longitude ?lon ;
|
||||
schema:address ?address .
|
||||
# Location (schema:location, not crm:P53)
|
||||
?custodian schema:location ?location .
|
||||
?location geo:lat ?lat ;
|
||||
geo:long ?lon .
|
||||
|
||||
# Identifiers (creates edges: custodian -> identifier)
|
||||
?custodian crm:P48_has_preferred_identifier ?identifier .
|
||||
?identifier a crm:E42_Identifier ;
|
||||
skos:inScheme ?scheme ;
|
||||
skos:notation ?notation ;
|
||||
schema:url ?identUrl .
|
||||
|
||||
# Digital platform / website
|
||||
?custodian foaf:homepage ?platform .
|
||||
?platform a hcc:DigitalPlatform ;
|
||||
schema:url ?platformUrl .
|
||||
|
||||
# Social media profiles (creates edges: custodian -> social)
|
||||
?custodian foaf:account ?social .
|
||||
?social a foaf:OnlineAccount ;
|
||||
hc:platform_type ?socialType ;
|
||||
foaf:accountName ?accountName ;
|
||||
foaf:accountServiceHomepage ?socialUrl .
|
||||
|
||||
# Wikidata/VIAF sameAs links (creates edges)
|
||||
?custodian owl:sameAs ?sameAs .
|
||||
|
||||
# GeoNames containedInPlace
|
||||
?custodian schema:containedInPlace ?geonames .
|
||||
# Persons linked to custodians
|
||||
?person a schema:Person ;
|
||||
rdfs:label ?personLabel ;
|
||||
schema:name ?personName ;
|
||||
schema:worksFor ?custodian ;
|
||||
org:memberOf ?custodian ;
|
||||
schema:jobTitle ?jobTitle .
|
||||
}
|
||||
WHERE {
|
||||
?custodian a crm:E39_Actor .
|
||||
OPTIONAL { ?custodian skos:prefLabel ?label }
|
||||
OPTIONAL { ?custodian skos:altLabel ?altLabel }
|
||||
OPTIONAL { ?custodian hc:custodian_type ?type }
|
||||
OPTIONAL { ?custodian dcterms:identifier ?dcId }
|
||||
|
||||
# Location
|
||||
# Get all custodians (nde:Custodian is the primary type)
|
||||
?custodian a nde:Custodian .
|
||||
OPTIONAL { ?custodian rdfs:label ?label }
|
||||
OPTIONAL { ?custodian skos:prefLabel ?prefLabel }
|
||||
OPTIONAL { ?custodian schema:name ?name }
|
||||
OPTIONAL { ?custodian hc:ghcid ?ghcid }
|
||||
OPTIONAL { ?custodian hc:isil ?isil }
|
||||
OPTIONAL { ?custodian schema:url ?website }
|
||||
OPTIONAL { ?custodian foaf:homepage ?homepage }
|
||||
OPTIONAL {
|
||||
?custodian crm:P53_has_former_or_current_location ?place .
|
||||
OPTIONAL { ?place schema:latitude ?lat }
|
||||
OPTIONAL { ?place schema:longitude ?lon }
|
||||
OPTIONAL { ?place schema:address ?address }
|
||||
?custodian owl:sameAs ?wikidata .
|
||||
FILTER(STRSTARTS(STR(?wikidata), "http://www.wikidata.org/"))
|
||||
}
|
||||
|
||||
# Identifiers
|
||||
# Location using schema:location (as generated by oxigraph_sync.py)
|
||||
OPTIONAL {
|
||||
?custodian crm:P48_has_preferred_identifier ?identifier .
|
||||
OPTIONAL { ?identifier skos:inScheme ?scheme }
|
||||
OPTIONAL { ?identifier skos:notation ?notation }
|
||||
OPTIONAL { ?identifier schema:url ?identUrl }
|
||||
?custodian schema:location ?location .
|
||||
OPTIONAL { ?location geo:lat ?lat }
|
||||
OPTIONAL { ?location geo:long ?lon }
|
||||
}
|
||||
|
||||
# Digital platform
|
||||
# Persons linked to custodians via schema:worksFor
|
||||
OPTIONAL {
|
||||
?custodian foaf:homepage ?platform .
|
||||
OPTIONAL { ?platform schema:url ?platformUrl }
|
||||
?person a schema:Person ;
|
||||
schema:worksFor ?custodian .
|
||||
OPTIONAL { ?person rdfs:label ?personLabel }
|
||||
OPTIONAL { ?person schema:name ?personName }
|
||||
OPTIONAL { ?person schema:jobTitle ?jobTitle }
|
||||
OPTIONAL { ?person org:memberOf ?custodian }
|
||||
}
|
||||
|
||||
# Social media
|
||||
OPTIONAL {
|
||||
?custodian foaf:account ?social .
|
||||
OPTIONAL { ?social hc:platform_type ?socialType }
|
||||
OPTIONAL { ?social foaf:accountName ?accountName }
|
||||
OPTIONAL { ?social foaf:accountServiceHomepage ?socialUrl }
|
||||
}
|
||||
|
||||
# External links
|
||||
OPTIONAL { ?custodian owl:sameAs ?sameAs }
|
||||
OPTIONAL { ?custodian schema:containedInPlace ?geonames }
|
||||
}
|
||||
LIMIT 500
|
||||
`;
|
||||
|
||||
let rdfData = '';
|
||||
|
|
@ -638,25 +621,17 @@ export function Visualize() {
|
|||
console.log(`Parsed: ${result.nodes.length} nodes, ${result.links.length} links`);
|
||||
loadGraphData(result);
|
||||
|
||||
// After loading, set filter to show just ONE random node type
|
||||
// This prevents overwhelming users with all ~500 nodes
|
||||
// Show ALL node types by default - no random filtering
|
||||
// Users can filter down using the sidebar controls if needed
|
||||
if (result.nodes.length > 0) {
|
||||
// Extract unique node types from the result
|
||||
const uniqueTypes = new Set(result.nodes.map(n => n.type));
|
||||
const typesArray = Array.from(uniqueTypes);
|
||||
|
||||
if (typesArray.length > 0) {
|
||||
// Pick one random type
|
||||
const randomIndex = Math.floor(Math.random() * typesArray.length);
|
||||
const randomType = typesArray[randomIndex];
|
||||
|
||||
// Set filter to only show this one type
|
||||
setFilters({ nodeTypes: new Set([randomType]) });
|
||||
|
||||
// Count nodes of this type
|
||||
const nodesOfType = result.nodes.filter(n => n.type === randomType);
|
||||
console.log(`RDF loaded: showing ${nodesOfType.length} nodes of type "${randomType}" (${result.nodes.length} total). Click "All" to see everything.`);
|
||||
}
|
||||
// Set filter to show ALL types by default
|
||||
setFilters({ nodeTypes: new Set(typesArray) });
|
||||
|
||||
console.log(`RDF loaded: showing all ${result.nodes.length} nodes across ${typesArray.length} types: ${typesArray.join(', ')}`);
|
||||
}
|
||||
|
||||
// Update cache state
|
||||
|
|
|
|||
Loading…
Reference in a new issue