Эффективная обработка ошибок и исключений в SPARQL - проблема конвертации в datetime из дат, извлеченных из DBpedia - PullRequest
0 голосов
/ 17 октября 2019

Я хотел определить возраст на момент смерти альпинистов, используя даты, указанные в DBpedia. Я быстро столкнулся с проблемой, когда в качестве даты указывалось 0, например, «1834-9-0». Это вызвало ошибку о том, что он не может быть преобразован в дату и время. Чтобы избежать этой ошибки, я хотел добавить фильтр с помощью функции DAY (), но сначала тип данных должен быть в datetime. Мой начальный код здесь:

#Problem code: 

PREFIX d: <http://dbpedia.org/ontology/>
SELECT ?firstAscentPerson ?died ?diedDatetime ?born 
       ( bif:datediff( 'year', xsd:dateTime( str(?born) ), xsd:dateTime( str(?died) ) ) ) AS ?age
WHERE 
  { 
    {
      SELECT DISTINCT ?firstAscentPerson ?mountainLabel ?climberName ?died ?diedDatetime ?born 
      FROM <http://dbpedia.org> 
      WHERE 
        { 
        ?country rdf:type d:Country.
        ?country dct:subject dbc:Countries_in_Europe.
        ?mountain d:locatedInArea ?country.
        ?mountain d:firstAscentYear ?firstAscent.
    ?mountain d:firstAscentPerson ?firstAscentPerson.
        ?firstAscentPerson d:deathDate ?died.
        ?firstAscentPerson d:birthDate ?born.

        BIND(xsd:dateTime(str(?died)) as ?diedDatetime)
        FILTER (DAY(?diedDatetime)>0)        

        }
      LIMIT 30
    }
  }

Чтобы фильтр работал для этой проблемы, я преобразовал дату в строку, разделил ее на день, месяц и год, а затем добавил фильтр, чтобы значения былибольше нуля:

# Verbose working code
PREFIX d: <http://dbpedia.org/ontology/>
SELECT ?firstAscentPerson ?bornCleaned ?diedCleaned
       ( bif:datediff( 'year', xsd:dateTime( ?bornCleaned ), xsd:dateTime( ?diedCleaned ) ) ) AS ?age
WHERE 
  { 
    {
      SELECT DISTINCT ?firstAscentPerson ?bornCleaned ?diedCleaned
      FROM <http://dbpedia.org> 
      WHERE 
        { 
        ?country rdf:type d:Country.
        ?country dct:subject dbc:Countries_in_Europe.
        ?mountain d:locatedInArea ?country.
        ?mountain d:firstAscentYear ?firstAscent.
    ?mountain d:firstAscentPerson ?firstAscentPerson.
        ?firstAscentPerson d:deathDate ?died.
        ?firstAscentPerson d:birthDate ?born.

        # 1. Convert the date to string

        BIND(str(?died) as ?diedString )
        BIND(str(?born) as ?bornString )

        # 2. Extract the date elements from the string 

        BIND(xsd:integer(strbefore(?diedString,"-")) as ?deathYear)
        BIND(strafter(?diedString,"-") as ?deathMonthDay) 
        BIND(xsd:integer(strafter(?deathMonthDay,"-")) as ?deathDay)
        BIND(xsd:integer(strbefore(?deathMonthDay,"-")) as ?deathMonth)

        BIND(xsd:integer(strbefore(?bornString,"-")) as ?bornYear)
        BIND(strafter(?bornString,"-") as ?bornMonthDay) 
        BIND(xsd:integer(strafter(?bornMonthDay,"-")) as ?bornDay)
        BIND(xsd:integer(strbefore(?bornMonthDay,"-")) as ?bornMonth)

        # 3. Concatenate the strings to provide a consistent date to prevent duplicates

        BIND(concat(str(?bornYear),"-",str(?bornMonth),"-",str(?bornDay)) as ?bornCleaned)
        BIND(concat(str(?deathYear),"-",str(?deathMonth),"-",str(?deathDay)) as ?diedCleaned)

        # 4. Filter the results to make sure the date is in the correct format

        FILTER(?deathDay > 0 && ?deathMonth > 0  && ?deathYear > 0 )
        FILTER(?bornDay > 0 && ?bornMonth > 0  && ?bornYear > 0 )

        }
      LIMIT 100
    }
  }

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

Существует ли что-то подобное в SPARQL, если да, то как это можно реализовать для этой проблемы? Или лучший способ запросить данные как можно лучше, а затем выполнить дополнительные преобразования и очистку в чем-то вроде Pandas?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...