Files
tools/graph/src/index.rs
T

95 lines
3.6 KiB
Rust
Raw Normal View History

2026-08-12 14:11:47 -04:00
use std::collections::HashMap;
use oxigraph::model::NamedNode;
use oxigraph::sparql::results::{QueryResultsFormat, QueryResultsParser, SliceQueryResultsParserOutput};
2026-08-13 09:44:46 -04:00
use gl_inference::tonic::transport::Channel;
2026-08-12 14:11:47 -04:00
use gl_inference::proto::ontology_client::OntologyClient;
use gl_inference::proto::OntologyQueryRequest;
use gl_search::{Field, OwnedValue, Schema};
use crate::class::Class;
use crate::{curie, CurieHelper};
use crate::helpers::{term_as_str, term_to_named_node};
use crate::language::LanguageCondition;
pub async fn index_ontology(
client: &mut OntologyClient<Channel>,
language: &LanguageCondition,
) -> crate::Result<Vec<HashMap<Field, OwnedValue>>> {
let curie_helper = CurieHelper::new((&*curie::PREFIXES).clone());
let label_filter = language.to_filter_expression("label");
let description_filter = language.to_filter_expression("description");
let mut request = OntologyQueryRequest::default();
request.sparql_query = format!(r#"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#>
SELECT ?class ?subject ?label ?description WHERE {{
VALUES ?class {{ rdf:Property rdfs:Class skos:Concept }}
?subject a ?class ;
rdfs:label ?label .
{label_filter}
OPTIONAL {{ ?subject rdfs:comment ?comment }}
OPTIONAL {{ ?subject skos:definition ?definition }}
BIND(COALESCE(?definition, ?comment) AS ?description)
{description_filter}
}}"#);
let response = client.query(request).await.unwrap();
let parser_output = QueryResultsParser::from_format(QueryResultsFormat::Json)
.for_slice(&response.get_ref().results)
.unwrap();
let mut results = Vec::new();
if let SliceQueryResultsParserOutput::Solutions(solutions) = parser_output {
let primary_language = language.primary_language();
let label_field = Schema::field("label", primary_language);
let definition_field = Schema::field("definition", primary_language);
for solution in solutions.filter_map(Result::ok) {
let mut document = HashMap::with_capacity(4);
let discriminant = solution
.get("class")
.and_then(term_to_named_node)
.and_then(Class::try_from_named_node)
.map(|doc_type| doc_type as u64)
.map(OwnedValue::U64)
.unwrap_or(OwnedValue::Null);
document.insert(Schema::discriminant_field(), discriminant);
let subject_str = solution
.get("subject")
.and_then(term_to_named_node)
.map(NamedNode::as_str);
let curie = subject_str
.and_then(|subject| curie_helper.abbreviate(None, subject))
.map(OwnedValue::Str)
.unwrap_or(OwnedValue::Null);
document.insert(Schema::curie_field(), curie);
let subject = subject_str
.map(OwnedValue::from)
.unwrap_or(OwnedValue::Null);
document.insert(Schema::iri_field(), subject);
let label = solution
.get("label")
.and_then(term_as_str)
.map(OwnedValue::from)
.unwrap_or(OwnedValue::Null);
document.insert(label_field, label);
let definition = solution
.get("description")
.and_then(term_as_str)
.map(OwnedValue::from)
.unwrap_or(OwnedValue::Null);
document.insert(definition_field, definition);
results.push(document);
}
}
Ok(results)
}