Подтвердить что ты не робот

Как написать запрос 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 .
}

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

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

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") )
}

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

4b9b3361

Ответ 1

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

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

Ответ 2

Из всех возможных операторов строк, которые вы можете использовать в 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")
}

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