.
This commit is contained in:
@@ -23,7 +23,4 @@ pub enum SearchError {
|
||||
|
||||
#[error(transparent)]
|
||||
SparqlSyntax(#[from] oxigraph::sparql::SparqlSyntaxError),
|
||||
|
||||
#[error("The provided DocType is not valid for this operation")]
|
||||
InvalidDocType,
|
||||
}
|
||||
|
||||
+29
-3
@@ -12,6 +12,7 @@ pub use tantivy::schema::document::{Document, Value};
|
||||
pub use tantivy::indexer::IndexWriter;
|
||||
|
||||
pub use error::{Result, SearchError};
|
||||
use gl_graph::vocab;
|
||||
pub use index::{SearchIndex, SearchIndexBuilder};
|
||||
pub use schema::Schema;
|
||||
|
||||
@@ -20,12 +21,37 @@ pub enum DocType {
|
||||
RdfsClass = 1,
|
||||
SkosConcept = 2,
|
||||
Person = 3,
|
||||
CorporateBody = 4,
|
||||
Work = 5,
|
||||
Expression = 6,
|
||||
Manifestation = 7,
|
||||
}
|
||||
|
||||
impl DocType {
|
||||
pub fn from_named_node(node: NamedNodeRef) -> Option<Self> {
|
||||
match node.as_str() {
|
||||
"http://rdaregistry.info/Elements/c/C10004" => Some(DocType::Person),
|
||||
pub fn to_named_node(&self) -> NamedNodeRef<'_> {
|
||||
match self {
|
||||
DocType::RdfProperty => vocab::rdf::PROPERTY,
|
||||
DocType::RdfsClass => vocab::rdfs::CLASS,
|
||||
DocType::SkosConcept => vocab::skos::CONCEPT,
|
||||
DocType::Person => vocab::rdac::PERSON,
|
||||
DocType::CorporateBody => vocab::rdac::CORPORATE_BODY,
|
||||
DocType::Work => vocab::rdac::WORK,
|
||||
DocType::Expression => vocab::rdac::EXPRESSION,
|
||||
DocType::Manifestation => vocab::rdac::MANIFESTATION,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_named_node<'a>(node: impl Into<NamedNodeRef<'a>>) -> Option<Self> {
|
||||
let node = node.into();
|
||||
match node {
|
||||
vocab::rdf::PROPERTY => Some(DocType::RdfProperty),
|
||||
vocab::rdfs::CLASS => Some(DocType::RdfsClass),
|
||||
vocab::skos::CONCEPT => Some(DocType::SkosConcept),
|
||||
vocab::rdac::PERSON => Some(DocType::Person),
|
||||
vocab::rdac::CORPORATE_BODY => Some(DocType::CorporateBody),
|
||||
vocab::rdac::WORK => Some(DocType::Work),
|
||||
vocab::rdac::EXPRESSION => Some(DocType::Expression),
|
||||
vocab::rdac::MANIFESTATION => Some(DocType::Manifestation),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
+68
-33
@@ -5,10 +5,11 @@ use oxigraph::sparql::{QueryResults, SparqlEvaluator};
|
||||
use oxigraph::store::Store;
|
||||
use tantivy::IndexWriter;
|
||||
use tantivy::schema::{Field, OwnedValue};
|
||||
use tracing::debug;
|
||||
use gl_graph::{vocab, CurieHelper};
|
||||
use crate::DocType;
|
||||
use crate::language::LanguageCondition;
|
||||
use crate::schema::Schema;
|
||||
use crate::SearchError::InvalidDocType;
|
||||
|
||||
fn term_to_named_node(term: &Term) -> Option<&NamedNode> {
|
||||
if let Term::NamedNode(node) = term {
|
||||
@@ -52,16 +53,15 @@ fn term_ref_as_str(term: TermRef<'_>) -> Option<&str> {
|
||||
}
|
||||
}
|
||||
|
||||
const GIVEN_NAME: NamedNodeRef = NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/a/datatype/P50292");
|
||||
const SURNAME: NamedNodeRef = NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/a/datatype/P50291");
|
||||
|
||||
pub fn index_entity(dataset: &Dataset, language: &LanguageCondition, writer: &IndexWriter<HashMap<Field, OwnedValue>>) -> crate::Result<usize> {
|
||||
let curie_helper = CurieHelper::new((&*gl_graph::PREFIXES).clone());
|
||||
|
||||
let mut subject_type_map = HashMap::new();
|
||||
for quad in dataset.quads_for_pattern(None, Some(rdf::TYPE), None, None) {
|
||||
if let NamedOrBlankNodeRef::NamedNode(subject) = quad.subject {
|
||||
subject_type_map.entry(subject)
|
||||
.and_modify(|types: &mut Vec<_>| types.push(quad.object))
|
||||
.or_insert_with(Vec::new);
|
||||
.or_insert_with(|| vec![quad.object]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,16 +69,24 @@ pub fn index_entity(dataset: &Dataset, language: &LanguageCondition, writer: &In
|
||||
for (subject, types) in subject_type_map {
|
||||
for type_ in types {
|
||||
if let Some(doc_type) = term_ref_as_named_node(type_).and_then(DocType::from_named_node) {
|
||||
match doc_type {
|
||||
DocType::Person => {
|
||||
let mut doc = index_person(dataset, subject, language);
|
||||
doc.insert(Schema::discriminant_field(), OwnedValue::U64(doc_type as u64));
|
||||
doc.insert(Schema::iri_field(), OwnedValue::Str(subject.as_str().to_string()));
|
||||
writer.add_document(doc)?;
|
||||
counter += 1;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let mut doc = match doc_type {
|
||||
DocType::Person => index_person(dataset, subject, language),
|
||||
DocType::CorporateBody => index_corporate_body(dataset, subject, language),
|
||||
_ => continue
|
||||
};
|
||||
|
||||
let subject_str = subject.as_str();
|
||||
|
||||
doc.insert(Schema::discriminant_field(), OwnedValue::U64(doc_type as u64));
|
||||
doc.insert(Schema::iri_field(), OwnedValue::Str(subject_str.to_string()));
|
||||
|
||||
let curie = curie_helper.abbreviate(None, subject_str)
|
||||
.map(OwnedValue::Str)
|
||||
.unwrap_or(OwnedValue::Null);
|
||||
doc.insert(Schema::curie_field(), curie);
|
||||
|
||||
writer.add_document(doc)?;
|
||||
counter += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,7 +95,7 @@ pub fn index_entity(dataset: &Dataset, language: &LanguageCondition, writer: &In
|
||||
}
|
||||
|
||||
fn index_person(dataset: &Dataset, subject: NamedNodeRef<'_>, language: &LanguageCondition) -> HashMap<Field, OwnedValue> {
|
||||
let given_name = dataset.quads_for_pattern(Some(subject.into()), Some(GIVEN_NAME), None, None)
|
||||
let given_name = dataset.quads_for_pattern(Some(subject.into()), Some(vocab::rdaad::GIVEN_NAME), None, None)
|
||||
.map(|q| q.object)
|
||||
.filter(|term| language.primary_matches_term(*term))
|
||||
.filter_map(term_ref_as_str)
|
||||
@@ -96,7 +104,7 @@ fn index_person(dataset: &Dataset, subject: NamedNodeRef<'_>, language: &Languag
|
||||
.next()
|
||||
.unwrap_or_else(|| OwnedValue::Null);
|
||||
|
||||
let surname = dataset.quads_for_pattern(Some(subject.into()), Some(SURNAME), None, None)
|
||||
let surname = dataset.quads_for_pattern(Some(subject.into()), Some(vocab::rdaad::SURNAME), None, None)
|
||||
.map(|q| q.object)
|
||||
.filter(|term| language.primary_matches_term(*term))
|
||||
.filter_map(term_ref_as_str)
|
||||
@@ -111,18 +119,30 @@ fn index_person(dataset: &Dataset, subject: NamedNodeRef<'_>, language: &Languag
|
||||
])
|
||||
}
|
||||
|
||||
pub fn index_triples(doc_type: DocType, store: Store, language: &LanguageCondition, writer: &IndexWriter<HashMap<Field, OwnedValue>>) -> crate::Result<usize> {
|
||||
fn index_corporate_body(dataset: &Dataset, subject: NamedNodeRef<'_>, language: &LanguageCondition) -> HashMap<Field, OwnedValue> {
|
||||
let name = dataset.quads_for_pattern(Some(subject.into()), Some(vocab::rdaad::NAME_OF_CORPORATE_BODY), None, None)
|
||||
.map(|q| q.object)
|
||||
.filter(|term| language.primary_matches_term(*term))
|
||||
.filter_map(term_ref_as_str)
|
||||
.map(String::from)
|
||||
.map(OwnedValue::Str)
|
||||
.next()
|
||||
.unwrap_or_else(|| OwnedValue::Null);
|
||||
|
||||
HashMap::from_iter([
|
||||
(Schema::field("corporate_name", language.primary_language()), name),
|
||||
])
|
||||
}
|
||||
|
||||
pub fn index_schema(store: Store, language: &LanguageCondition, writer: &IndexWriter<HashMap<Field, OwnedValue>>) -> crate::Result<usize> {
|
||||
let curie_helper = CurieHelper::new((&*gl_graph::PREFIXES).clone());
|
||||
|
||||
let label_filter = language.to_filter_expression("label");
|
||||
let description_filter = language.to_filter_expression("description");
|
||||
let rdf_type = match doc_type {
|
||||
DocType::RdfsClass => Ok("rdfs:Class"),
|
||||
DocType::RdfProperty => Ok("rdf:Property"),
|
||||
DocType::SkosConcept => Ok("skos:Concept"),
|
||||
_ => Err(InvalidDocType),
|
||||
}?;
|
||||
|
||||
let query = format!(r#"SELECT ?subject ?label ?description WHERE {{
|
||||
?subject a {rdf_type} ;
|
||||
let query = format!(r#"SELECT ?class ?subject ?label ?description WHERE {{
|
||||
VALUES ?class {{ rdf:Property rdfs:Class skos:Concept }}
|
||||
?subject a ?class ;
|
||||
rdfs:label ?label .
|
||||
{label_filter}
|
||||
|
||||
@@ -141,17 +161,32 @@ pub fn index_triples(doc_type: DocType, store: Store, language: &LanguageConditi
|
||||
let mut counter = 0usize;
|
||||
let query_results = sparql.on_store(&store).execute()?;
|
||||
if let QueryResults::Solutions(solutions) = query_results {
|
||||
let discriminant = OwnedValue::U64(doc_type as u64);
|
||||
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);
|
||||
document.insert(Schema::discriminant_field(), discriminant.clone());
|
||||
|
||||
let subject = solution.get("subject")
|
||||
let discriminant = solution.get("class")
|
||||
.and_then(term_to_named_node)
|
||||
.map(NamedNode::as_str)
|
||||
.map(OwnedValue::from)
|
||||
.and_then(DocType::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);
|
||||
|
||||
@@ -159,13 +194,13 @@ pub fn index_triples(doc_type: DocType, store: Store, language: &LanguageConditi
|
||||
.and_then(term_as_str)
|
||||
.map(OwnedValue::from)
|
||||
.unwrap_or(OwnedValue::Null);
|
||||
document.insert(Schema::field("label", primary_language), label);
|
||||
document.insert(label_field, label);
|
||||
|
||||
let definition = solution.get("description")
|
||||
.and_then(term_as_str)
|
||||
.map(OwnedValue::from)
|
||||
.unwrap_or(OwnedValue::Null);
|
||||
document.insert(Schema::field("definition", primary_language), definition);
|
||||
document.insert(definition_field, definition);
|
||||
|
||||
writer.add_document(document)?;
|
||||
counter += 1;
|
||||
|
||||
@@ -33,6 +33,7 @@ impl Schema {
|
||||
|
||||
schema_builder.add_text_field("surname:en", stored_ngram32.clone());
|
||||
schema_builder.add_text_field("given_name:en", stored_ngram32.clone());
|
||||
schema_builder.add_text_field("corporate_name:en", stored_ngram32.clone());
|
||||
|
||||
schema_builder.add_u64_field("subtitle_start", schema::STORED);
|
||||
schema_builder.add_u64_field("subtitle_end", schema::STORED);
|
||||
|
||||
Reference in New Issue
Block a user