Как написать запрос SPARQL, который эффективно соответствует строковым литералам, игнорируя регистр

я использую Jena ARQ для написания запроса SPARQL против большой онтологии, считываемой из Jena TDB, чтобы найти типы, связанные с концепциями на основе метки rdfs:

SELECT DISTINCT ?type WHERE {
 ?x <http://www.w3.org/2000/01/rdf-schema#label> "aspirin" .
 ?x <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type .
}

это работает довольно хорошо, и на самом деле довольно быстрое ("Tylenol" находится в онтологии, но не "tylenol" следующий запрос приходит пусто:

SELECT DISTINCT ?type WHERE {
 ?x <http://www.w3.org/2000/01/rdf-schema#label> "tylenol" .
 ?x <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type .
}

Я могу написать нечувствительную к регистру версию этого запроса, используя синтаксис фильтра, например:

SELECT DISTINCT ?type WHERE {
 ?x <http://www.w3.org/2000/01/rdf-schema#label> ?term .
 ?x <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type .
 FILTER ( regex (str(?term), "tylenol", "i") )
}

но теперь запрос занимает более минуты, чтобы завершить! Есть ли способ написать запрос без учета регистра более эффективным способом?

2 ответов


причина, по которой запрос с запросом фильтра работает медленнее, заключается в том, что ?термин не связан он требует сканирования индекса PSO или POS, чтобы найти все операторы с предикатом rdfs:label и отфильтровать их от регулярного выражения. Когда он был привязан к конкретному ресурсу (в вашем первом примере), он мог использовать индекс OPS или POS для сканирования только операторов с предикатом rdfs:label и указанным ресурсом объекта, который имел бы гораздо более низкую мощность.

общее решение для этого типа текстового поиска проблема заключается в использовании внешнего текстового индекса. В этом случае Jena предоставляет бесплатный текстовый индекс под названием LARQ, который использует Lucene для поиска и объединяет результаты с остальной частью запроса.


из всех возможных строковых операторов, которые вы можете использовать в SPARQL,regex вероятно, самый дорогой. Ваш запрос может работать быстрее, если вы избегаете regex и вы используете UCASE или LCASE С обеих сторон теста вместо этого. Что-то вроде:

SELECT DISTINCT ?type WHERE {
 ?x <http://www.w3.org/2000/01/rdf-schema#label> ?term .
 ?x <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type .
 FILTER (lcase(str(?term)) = "tylenol")
}

Это может быть быстрее, но в целом не ожидайте большой производительности для текстового поиска с любым тройным магазином. Тройные магазины очень хороши в сопоставлении графов и не так хороши в сопоставлении строк.