.
This commit is contained in:
+5
-5
@@ -44,7 +44,7 @@ pub(crate) enum Message {
|
|||||||
UnhoverRow(QuadKey),
|
UnhoverRow(QuadKey),
|
||||||
QueryUpdated(String),
|
QueryUpdated(String),
|
||||||
SetSearchResults(Vec<SearchDocument>),
|
SetSearchResults(Vec<SearchDocument>),
|
||||||
QueryTypeUpdated(NamedNode),
|
QueryTypeUpdated(LabeledIri),
|
||||||
SearchResultClicked(NamedNode),
|
SearchResultClicked(NamedNode),
|
||||||
DatatypeUpdated(QuadKey, Option<String>),
|
DatatypeUpdated(QuadKey, Option<String>),
|
||||||
LanguageUpdated(QuadKey, Option<String>),
|
LanguageUpdated(QuadKey, Option<String>),
|
||||||
@@ -117,6 +117,7 @@ impl Publisher {
|
|||||||
let mut document = doc!(
|
let mut document = doc!(
|
||||||
Schema::type_field() => entry.catalog_id,
|
Schema::type_field() => entry.catalog_id,
|
||||||
Schema::iri_field() => individual.as_str(),
|
Schema::iri_field() => individual.as_str(),
|
||||||
|
Schema::curie_field() => ontology.abbreviate(individual.as_ref()),
|
||||||
);
|
);
|
||||||
for (key, value) in entry.fields {
|
for (key, value) in entry.fields {
|
||||||
document.add_text(Schema::field(&key, language::ENGLISH_PRIMARY), value.as_str());
|
document.add_text(Schema::field(&key, language::ENGLISH_PRIMARY), value.as_str());
|
||||||
@@ -328,9 +329,8 @@ impl Publisher {
|
|||||||
}
|
}
|
||||||
Message::QueryTypeUpdated(type_) => {
|
Message::QueryTypeUpdated(type_) => {
|
||||||
if let Some(search_state) = &mut self.search_state {
|
if let Some(search_state) = &mut self.search_state {
|
||||||
if let Some(type_) = self.ontology.labeled_entity(&type_) {
|
search_state.type_ = type_;
|
||||||
search_state.type_ = type_;
|
task = Task::done(Message::QueryUpdated(search_state.query.clone()));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::QueryUpdated(new_query) => {
|
Message::QueryUpdated(new_query) => {
|
||||||
@@ -676,7 +676,7 @@ impl Publisher {
|
|||||||
entities.sort_by(|a, b| Ord::cmp(&a.label, &b.label));
|
entities.sort_by(|a, b| Ord::cmp(&a.label, &b.label));
|
||||||
|
|
||||||
let type_selector = pick_list(Some(&search_state.type_), entities, ToString::to_string)
|
let type_selector = pick_list(Some(&search_state.type_), entities, ToString::to_string)
|
||||||
.on_select(|selection| Message::QueryTypeUpdated(selection.iri));
|
.on_select(|selection| Message::QueryTypeUpdated(selection));
|
||||||
|
|
||||||
let fields = self.ontology.fields_for_class(&search_state.type_.iri, &*language::ENGLISH_OR_UNTAGGED)
|
let fields = self.ontology.fields_for_class(&search_state.type_.iri, &*language::ENGLISH_OR_UNTAGGED)
|
||||||
.expect("Unable to load fields for class");
|
.expect("Unable to load fields for class");
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use oxigraph::model::{NamedNode, Quad, Term};
|
use oxigraph::model::{NamedNode, Quad, Term};
|
||||||
use oxigraph::model::vocab::{rdf, xsd};
|
use oxigraph::model::vocab::{rdf, xsd};
|
||||||
use oxilangtag::LanguageTag;
|
|
||||||
|
|
||||||
pub fn quad_into_term(quad: Quad) -> Term {
|
pub fn quad_into_term(quad: Quad) -> Term {
|
||||||
quad.object
|
quad.object
|
||||||
@@ -61,4 +60,8 @@ pub fn term_to_u64(term: &Term) -> Option<u64> {
|
|||||||
let value: u64 = literal.value().parse().expect("Failed to parse u64 from ontology. It ought to be a non-negative integer.");
|
let value: u64 = literal.value().parse().expect("Failed to parse u64 from ontology. It ought to be a non-negative integer.");
|
||||||
Some(value)
|
Some(value)
|
||||||
} else { None }
|
} else { None }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn term_into_u64(term: Term) -> Option<u64> {
|
||||||
|
term_to_u64(&term)
|
||||||
}
|
}
|
||||||
+10
-65
@@ -8,11 +8,8 @@ use std::collections::{BTreeMap, HashMap, HashSet};
|
|||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::LazyLock;
|
use std::sync::LazyLock;
|
||||||
use iced::widget::sensor::Key;
|
|
||||||
use oxigraph::store::Store;
|
use oxigraph::store::Store;
|
||||||
use oxilangtag::LanguageTag;
|
use crate::rdf::conversion;
|
||||||
use tracing::{debug, debug_span};
|
|
||||||
use crate::rdf::{conversion, language, materialize};
|
|
||||||
use crate::rdf::language::LanguageCondition;
|
use crate::rdf::language::LanguageCondition;
|
||||||
|
|
||||||
static PREFIXES: LazyLock<BTreeMap<String, String>> = LazyLock::new(|| {
|
static PREFIXES: LazyLock<BTreeMap<String, String>> = LazyLock::new(|| {
|
||||||
@@ -78,49 +75,11 @@ impl OntologyBuilder {
|
|||||||
materialize::super_classes(&mut store)?;
|
materialize::super_classes(&mut store)?;
|
||||||
debug_span!("Optimize Ontology").in_scope(|| store.optimize())?;*/
|
debug_span!("Optimize Ontology").in_scope(|| store.optimize())?;*/
|
||||||
|
|
||||||
let mut entities: HashMap<NamedNode, Entity> = HashMap::new();
|
|
||||||
// All Entities have exactly one catalog ID.
|
|
||||||
/*for quad in store.quads_for_pattern(None, Some(gl::CATALOG_ID), None, None)
|
|
||||||
.filter_map(Result::ok) {
|
|
||||||
let label = store.quads_for_pattern(Some(quad.subject.as_ref().into()), Some(rdfs::LABEL), None, None)
|
|
||||||
.filter_map(Result::ok)
|
|
||||||
.map(conversion::quad_into_term)
|
|
||||||
.filter(|term| conversion::language_matches(term, &conversion::english()))
|
|
||||||
.filter_map(conversion::term_into_string)
|
|
||||||
.next();
|
|
||||||
|
|
||||||
let comment = store.quads_for_pattern(Some(quad.subject.as_ref().into()), Some(rdfs::COMMENT), None, None)
|
|
||||||
.filter_map(Result::ok)
|
|
||||||
.map(conversion::quad_into_term)
|
|
||||||
.filter(|term| conversion::language_matches(term, &conversion::english()))
|
|
||||||
.filter_map(conversion::term_into_string)
|
|
||||||
.next();
|
|
||||||
|
|
||||||
if let Some(catalog_id) = conversion::term_to_u64(&quad.object) &&
|
|
||||||
let NamedOrBlankNode::NamedNode(subject) = quad.subject &&
|
|
||||||
let Some(label) = label {
|
|
||||||
let mut properties = HashSet::new();
|
|
||||||
for quad in store.quads_for_pattern(Some(subject.as_ref().into()), Some(gl::ASSOCIATED_PROPERTY), None, None)
|
|
||||||
.filter_map(Result::ok) {
|
|
||||||
if let Term::NamedNode(property) = quad.object {
|
|
||||||
properties.insert(property);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
entities.insert(subject, Entity {
|
|
||||||
label,
|
|
||||||
comment,
|
|
||||||
catalog_id,
|
|
||||||
properties,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
let mut indexed_by = HashMap::new();
|
let mut indexed_by = HashMap::new();
|
||||||
for quad in store.quads_for_pattern(None, Some(gl::INDEXED_BY_FIELD), None, None)
|
for quad in store.quads_for_pattern(None, Some(gl::INDEXED_BY_FIELD), None, None)
|
||||||
.filter_map(Result::ok) {
|
.filter_map(Result::ok) {
|
||||||
if let NamedOrBlankNode::NamedNode(subject) = quad.subject
|
if let NamedOrBlankNode::NamedNode(subject) = quad.subject
|
||||||
&& let Term::NamedNode(field) = quad.object
|
&& let Term::NamedNode(field) = quad.object {
|
||||||
{
|
|
||||||
indexed_by.insert(subject, field);
|
indexed_by.insert(subject, field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,8 +87,6 @@ impl OntologyBuilder {
|
|||||||
Ok(Ontology {
|
Ok(Ontology {
|
||||||
store,
|
store,
|
||||||
prefixes,
|
prefixes,
|
||||||
entities,
|
|
||||||
indexed_by,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,12 +131,6 @@ pub struct IndexField {
|
|||||||
pub struct Ontology {
|
pub struct Ontology {
|
||||||
store: Store,
|
store: Store,
|
||||||
prefixes: HashMap<String, String>,
|
prefixes: HashMap<String, String>,
|
||||||
|
|
||||||
// NamedIndividual of class Entity -> Rust Type
|
|
||||||
entities: HashMap<NamedNode, Entity>,
|
|
||||||
|
|
||||||
// Property -> NamedIndividual of class IndexField
|
|
||||||
indexed_by: HashMap<NamedNode, NamedNode>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ontology {
|
impl Ontology {
|
||||||
@@ -235,6 +186,14 @@ WHERE {{
|
|||||||
Ok(results)
|
Ok(results)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn catalog_id(&self, class: &NamedNode) -> Option<u64> {
|
||||||
|
self.store.quads_for_pattern(Some(class.into()), Some(gl::CATALOG_ID), None, None)
|
||||||
|
.filter_map(Result::ok)
|
||||||
|
.map(conversion::quad_into_term)
|
||||||
|
.filter_map(conversion::term_into_u64)
|
||||||
|
.next()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fields_for_class(&self, class: &NamedNode, language: &LanguageCondition) -> error::Result<Vec<IndexField>> {
|
pub fn fields_for_class(&self, class: &NamedNode, language: &LanguageCondition) -> error::Result<Vec<IndexField>> {
|
||||||
let language_filter = language.to_filter_expression("label");
|
let language_filter = language.to_filter_expression("label");
|
||||||
let query = format!(r#"SELECT DISTINCT ?name ?label {{
|
let query = format!(r#"SELECT DISTINCT ?name ?label {{
|
||||||
@@ -288,12 +247,6 @@ WHERE {{
|
|||||||
.map(|base| NamedNode::new_unchecked(format!("{base}{name}")))
|
.map(|base| NamedNode::new_unchecked(format!("{base}{name}")))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn catalog_id(&self, class: &NamedNode) -> Option<u64> {
|
|
||||||
self.entities
|
|
||||||
.get(class)
|
|
||||||
.map(|entity| entity.catalog_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn info(&self, iri: &NamedNode, language: &LanguageCondition) -> LabeledIri {
|
pub fn info(&self, iri: &NamedNode, language: &LanguageCondition) -> LabeledIri {
|
||||||
let label = self.store.quads_for_pattern(Some(iri.as_ref().into()), Some(rdfs::LABEL), None, None)
|
let label = self.store.quads_for_pattern(Some(iri.as_ref().into()), Some(rdfs::LABEL), None, None)
|
||||||
.filter_map(Result::ok)
|
.filter_map(Result::ok)
|
||||||
@@ -309,14 +262,6 @@ WHERE {{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn labeled_entity(&self, class: &NamedNode) -> Option<LabeledIri> {
|
|
||||||
self.entities.get(class)
|
|
||||||
.map(|entity| LabeledIri {
|
|
||||||
iri: class.to_owned(),
|
|
||||||
label: entity.label.to_owned(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn labeled_entities(&self, language: &LanguageCondition) -> impl Iterator<Item = LabeledIri> {
|
pub fn labeled_entities(&self, language: &LanguageCondition) -> impl Iterator<Item = LabeledIri> {
|
||||||
self.store.quads_for_pattern(None, Some(rdf::TYPE), Some(gl::ENTITY.into()), None)
|
self.store.quads_for_pattern(None, Some(rdf::TYPE), Some(gl::ENTITY.into()), None)
|
||||||
.filter_map(Result::ok)
|
.filter_map(Result::ok)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ impl Schema {
|
|||||||
let mut schema_builder = TantivySchema::builder();
|
let mut schema_builder = TantivySchema::builder();
|
||||||
schema_builder.add_u64_field("type", schema::FAST | schema::INDEXED);
|
schema_builder.add_u64_field("type", schema::FAST | schema::INDEXED);
|
||||||
schema_builder.add_text_field("iri", schema::STORED | schema::STRING);
|
schema_builder.add_text_field("iri", schema::STORED | schema::STRING);
|
||||||
|
schema_builder.add_text_field("curie", stored_ngram32.clone());
|
||||||
|
|
||||||
schema_builder.add_text_field("label:en", stored_ngram32.clone());
|
schema_builder.add_text_field("label:en", stored_ngram32.clone());
|
||||||
schema_builder.add_text_field("definition:en", stored_en_stem.clone());
|
schema_builder.add_text_field("definition:en", stored_en_stem.clone());
|
||||||
@@ -45,6 +46,10 @@ impl Schema {
|
|||||||
Self::schema().get_field("iri").unwrap()
|
Self::schema().get_field("iri").unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn curie_field() -> Field {
|
||||||
|
Self::schema().get_field("curie").unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn field(name: &str, language: &str) -> Field {
|
pub fn field(name: &str, language: &str) -> Field {
|
||||||
Schema::schema()
|
Schema::schema()
|
||||||
.get_field(&format!("{name}:{language}"))
|
.get_field(&format!("{name}:{language}"))
|
||||||
|
|||||||
Reference in New Issue
Block a user