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

StackOverflow https://stackoverflow.com//questions/10660030

  •  11-12-2019
  •  | 
  •  

Вопрос

Я использую 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") )
}

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

Это было полезно?

Решение

Причина, по которой запрос с запросом FILTER выполняется медленнее, заключается в том, что ?term не привязан и требует сканирования индекса 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")
}

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top