Как написать запрос 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")
}
Это может быть быстрее, но в целом не ожидайте большой производительности для текстового поиска с любым тройным магазином. Тройные магазины очень хороши в сопоставлении графов и не так хороши в сопоставлении строк.