Сделайте фильтрацию людей по критериям рождения, смерти и года более эффективными в запросе SPARQL - PullRequest
0 голосов
/ 01 ноября 2018

Я хочу найти примеры ученых, которые оба родились и умерли в первые числа лет. Основываясь на предыдущем обсуждении на этом URL , я разработал следующий запрос, который является громоздким и время ожидания:

SELECT ?birthYear ?deathYear ?scientist ?scientistLabel 
WHERE 
{ 
 {
  select ?value1
    { 
      ?number wdt:P31 wd:Q49008. 
      ?number wdt:P1181 ?value1 
      filter(?value1 < year(now())) 
    }
  }
  {
  select ?value2
    { 
      ?number wdt:P31 wd:Q49008. 
      ?number wdt:P1181 ?value2 
      filter(?value2 < ?value1)
    }
  }
  ?scientist wdt:P106 wd:Q901. 
  ?scientist wdt:P570 ?deathDate.
  ?scientist wdt:P569 ?birthDate
  BIND(year(?deathDate) as ?deathYear) 
  BIND(year(?birthDate) as ?birthYear)
  filter(?deathYear = ?value1)
  filter(?birthYear = ?value2)
  SERVICE wikibase:label { bd:serviceParam wikibase:language " [AUTO_LANGUAGE],en". } 
} 
order by asc(?deathYear) asc(?scientistLabel) 
limit 100

Я новичок в SPARQL, но, насколько я могу судить, для этого понадобятся пары простых чисел, а затем выясняется, умер ли кто-либо, чья профессия "ученый", в год, соответствующий первому, тогда, если этот человек родился в год, соответствующий 2-му. Есть ли способ повысить производительность этого запроса?

1 Ответ

0 голосов
/ 02 ноября 2018

По вашему запросу есть 2 проблемы:

  1. Нельзя таким образом передавать значения в подзапрос (см. Семантика снизу вверх ).
  2. Значения wdt:P1181 равны xsd:decimal с, тогда как year() возвращает xsd:integer с. Нужно использовать FILTER(?birthYear = ?value), который менее производительный и менее оптимизируемый, чем простые объединения. Похоже, что Blazegraph должен материализовать решения преждевременно.

Следовательно, ваш запрос должен быть:

SELECT DISTINCT ?scientist ?scientistLabel ?birthYear ?deathYear {
  {
    SELECT (xsd:integer(?value1) as ?birthYear) { 
      ?number wdt:P31 wd:Q49008. 
      ?number wdt:P1181 ?value1 
      FILTER(?value1 < year(now())) 
    }
  }
  {
    SELECT (xsd:integer(?value2) AS ?deathYear) { 
      ?number wdt:P31 wd:Q49008. 
      ?number wdt:P1181 ?value2 
      FILTER(?value2 < year(now()))
    }
  }
  ?scientist wdt:P106 wd:Q901.
  ?scientist wdt:P570 ?deathDate.
  ?scientist wdt:P569 ?birthDate.
  FILTER(isLiteral(?birthDate) && isLiteral(?deathDate))
  BIND(year(?deathDate) AS ?deathYear) 
  BIND(year(?birthDate) AS ?birthYear)
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". } 
} ORDER BY ASC(?birthDate) ASC(?deathDate)

Попробуйте

Я также добавил FILTER(isLiteral(?birthDate)), потому что значения wdt:P1181 могут быть неизвестными значениями (т. Е. Пустые узлы RDF), в этом случае BIND (year(?birthDate) AS ?birthYear) проецирует переменную, которая всегда не связана и соответствует все в соединении.


Вы можете еще быстрее ускорить запрос, используя специальные приемы Blazegraph:

SELECT DISTINCT ?scientist ?scientistLabel ?birthYear ?deathYear
   WITH {
    SELECT (xsd:integer(?value) AS ?year) {
      [] wdt:P31 wd:Q49008 ; wdt:P1181 ?value. 
      hint:Prior hint:rangeSafe true.
      FILTER(?value  <= year(now()))
    }
  } AS %primes {
    # hint:Query hint:maxParallel 50 . 
    # hint:Query hint:chunkSize 250 . 
  { SELECT (?year AS ?birthYear)  { include %primes } }
  { SELECT (?year AS ?deathYear)  { include %primes } } 
  ?scientist wdt:P106 wd:Q901.
  ?scientist wdt:P570 ?deathDate.
  ?scientist wdt:P569 ?birthDate.
  FILTER (isLiteral(?deathDate) && isLiteral(?birthDate))
  BIND (year(?birthDate) AS ?birthYear)
  BIND (year(?deathDate) AS ?deathYear)
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
} ORDER BY ASC(?birthYear) ASC (?deathYear)

Попробуйте

...