SPARQL на примерах Wikidata: различия между версиями
D1g (обсуждение | вклад) |
Нет описания правки |
||
(не показано 65 промежуточных версий 2 участников) | |||
Строка 1: | Строка 1: | ||
{{Статья| | {{Статья|Опубликована|sparql_wikidata}} | ||
{{Аннотация|SPARQL это язык запросов к данным, основанных на модели "субъект-предикат-значение". Wikidata | {{Аннотация|SPARQL — это язык запросов к данным, основанных на модели "субъект-предикат-объект" (примечание: "объект" часто заменяется на "значение", особенно в случае количественных предикатов) (в терминах Wikidata элемент-[https://www.wikidata.org/wiki/Help:Statements/ru свойство-значения], item-property-values). Wikidata — открытый проект, потенциально интересный в гео-проектах и доступный в виде публичной SPARQL-точки}} | ||
== Инструментарий запросов == | == Инструментарий запросов == | ||
Запросы к Wikidata можно составлять с помощью различных SPARQL клиентов | Запросы к Wikidata можно составлять с помощью различных SPARQL-клиентов. Ключевая особенность Wikidata — это общедоступная и публичная точка доступа SPARQL, включающая в том числе простой [https://query.wikidata.org веб-интерфейс]. | ||
=== query.wikidata.org === | === query.wikidata.org === | ||
https:// | У сервиса query.wikidata.org есть целое руководство на английском языке https://www.mediawiki.org/wiki/Wikidata_query_service/User_Manual и репозиторий для разработчиков https://github.com/wikimedia/wikidata-query-rdf. | ||
Обратите внимание, что результаты запросов можно скачать в формате CSV — хорошее подспорье для более серьёзной работы при помощи других инструментов. | |||
Обратите внимание, что результаты запросов можно скачать в формате CSV | |||
В таблице результатов (в нижней части экрана) можно отфильтровать результаты, используя поиск по всем полям сразу (например, можно попробовать найти "Moscow"). | В таблице результатов (в нижней части экрана) можно отфильтровать результаты, используя поиск по всем полям сразу (например, можно попробовать найти "Moscow"). | ||
== Wikidata == | == Wikidata == | ||
=== | Для помощи по терминологии и модели Wikidata можно посмотреть сюда: [https://www.wikidata.org/wiki/Wikidata:Glossary/ru Викиданные:Глоссарий]. | ||
Структуру ''элемента'' (item) и ''свойства'' (property) можно найти на англоязычной странице [https://www.mediawiki.org/wiki/Wikibase/DataModel/Primer Wikibase/DataModel/Primer]. | |||
* ''Множественные значения'' | |||
* ''Отсутствующие значения'' (известно, что значения не может быть) эквивалентны тегам ключ=no из OpenStreetMap - описаны на странице ''[https://www.wikidata.org/wiki/Help:Statements/ru Help:Утверждения]'' | |||
* ''Значение не определено'' (известно, что значение есть, но не известно какое) - описаны на той же странице | |||
[https://commons.wikimedia.org/wiki/File:Wikidata_statement_ru.svg Диаграмма русскоязычной терминологии утверждений в Викиданных] | |||
=== Свойства Wikidata === | |||
Полный перечень свойств: [https://www.wikidata.org/wiki/Wikidata:List_of_properties Wikidata:List_of_properties] | |||
Отчёт количества использований каждого свойства - [https://www.wikidata.org/wiki/Wikidata:Database_reports/List_of_properties/all Wikidata:Database_reports/List_of_properties/all] | |||
* дата прекращения существования - https://www.wikidata.org/wiki/Property:P576 | * дата прекращения существования - https://www.wikidata.org/wiki/Property:P576 | ||
* дата окончания - https://www.wikidata.org/wiki/Property:P582 | * дата окончания - https://www.wikidata.org/wiki/Property:P582 | ||
=== Географические | === Географические свойства в Wikidata === | ||
Полный перечень: [https://www.wikidata.org/wiki/Special:MyLanguage/Wikidata:List_of_properties/Geographical_feature Wikidata:List_of_properties/Geographical_feature] | |||
=== Географические | |||
<!-- Больше миллиона --> | |||
: Принадлежность стране - https://www.wikidata.org/wiki/Property:P17 | |||
: Принадлежность админ делению - https://www.wikidata.org/wiki/Property:P131 | |||
: Координаты (точка) - https://www.wikidata.org/wiki/Property:P625 (при выборке этого свойства появляется возможность представить результаты на карте в нижней части экрана) | |||
<!-- Более 100 тысяч, но менее миллиона --> | |||
: Численность населения - https://www.wikidata.org/wiki/Property:P1082 | |||
<!-- Более 10 тысяч, но менее 100 тысяч --> | |||
: ID отношения из OpenStreetMap - https://www.wikidata.org/wiki/Property:P402 | |||
: Столица - https://www.wikidata.org/wiki/Property:P36 | |||
: Город-побратим - https://www.wikidata.org/wiki/Property:P190 | |||
<!-- Редкие, менее 10000 --> | |||
: Относительная высота https://www.wikidata.org/wiki/Property:P2660 | |||
: Официальный язык - https://www.wikidata.org/wiki/Property:P37 | |||
=== Российские свойства в Wikidata === | |||
* код ОКАТО https://www.wikidata.org/wiki/Property:P721 | |||
* код ОКТМО https://www.wikidata.org/wiki/Property:P764 | |||
* Портал «Герои страны» ID https://www.wikidata.org/wiki/Property:P2943 | |||
=== Географические элементы в Wikidata === | |||
* континент - https://www.wikidata.org/wiki/Q5107 | * континент - https://www.wikidata.org/wiki/Q5107 | ||
* суверенное государство - https://www.wikidata.org/wiki/Q3624078 | * суверенное государство - https://www.wikidata.org/wiki/Q3624078 | ||
Строка 38: | Строка 69: | ||
* город - https://www.wikidata.org/wiki/Q515 | * город - https://www.wikidata.org/wiki/Q515 | ||
* | * Северный полюс - https://www.wikidata.org/wiki/Q934 | ||
* | * Южный полюс - https://www.wikidata.org/wiki/Q933 | ||
* гора - https://www.wikidata.org/wiki/Q8502 | * гора - https://www.wikidata.org/wiki/Q8502 | ||
== Элементы SPARQL запросов == | == Wikidata Blazegraph == | ||
Blazegraph — расширение от Wikidata к [https://www.blazegraph.com/ Blazegraph], чтобы сделать запросы к Wikibase более эффективными. Имеет лицензию GPLv2. | |||
* Функция [https://github.com/wikimedia/wikidata-query-rdf/blob/master/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/constraints/WikibaseDistanceBOp.java geof:distance] возвращает минимальное расстояние между двумя точками. | |||
== Элементы SPARQL-запросов == | |||
Т.к. исходные данные представляют граф (элемент-свойство-значения) и его модификации (в Wikidata: квалификаторы, ссылки и др.), то большинство SPARQL-запросов строятся вокруг поиска ''паттернов в графе''<ref>https://www.w3.org/TR/sparql11-query/#GraphPattern</ref>, зачастую нескольких. | |||
=== Города в России с телефонными кодами === | === Города в России с телефонными кодами === | ||
Самый простой пример. | Самый простой пример. | ||
* 1 строка: SELECT запросы<ref>https://www.w3.org/TR/sparql11-query/#QueryForms</ref> выбирают данные или их часть | * 1 строка: SELECT запросы<ref>https://www.w3.org/TR/sparql11-query/#QueryForms</ref> выбирают данные или их часть | ||
* 2 строка: выбираем субъекты (?item) у которых явно указано, что они в стране - ''Россия'' (Q159) | * 2 строка: выбираем субъекты (?item), у которых явно указано, что они в стране - ''Россия'' (Q159) | ||
* 3 строка: выбираем субъекты (?item) у которых явно указано, что они суть - ''города'' (Q515) | * 3 строка: выбираем субъекты (?item), у которых явно указано, что они суть - ''города'' (Q515) | ||
* 4-6 строка: т.к. значения предиката "ID отношения из OpenStreetMap" P402 могут быть просто не заполнены у отдельных объектов, такие объекты будут исключены из результатов. Это не совсем интуитивно понятно для людей, привыкших к SQL-запросам (где NULL-значения возвращаются в большинстве случаев). В SPARQL ''необязательные значения''<ref>https://www.w3.org/TR/sparql11-query/#optionals</ref> нужно включать в результаты вручную. | * 4-6 строка: т.к. значения предиката "ID отношения из OpenStreetMap" P402 могут быть просто не заполнены у отдельных объектов, такие объекты будут исключены из результатов. Это не совсем интуитивно понятно для людей, привыкших к SQL-запросам (где NULL-значения возвращаются в большинстве случаев). В SPARQL ''необязательные значения''<ref>https://www.w3.org/TR/sparql11-query/#optionals</ref> нужно включать в результаты вручную. | ||
* 7 строка: выбираем все возможные субъекты и объекты у предиката P473 (код города). Примечание о части "?localdialingcode": в Wikidata у [https://www.wikidata.org/wiki/Q649 Москвы] указано сразу два объекта "495" и "499" у предиката P473, поэтому вернутся 2 результата, а не один. В SQL пришлось бы писать JOIN на ровном месте, а в SPARQL его нет вообще. | * 7 строка: выбираем все возможные субъекты и объекты у предиката P473 (код города). Примечание о части "?localdialingcode": в Wikidata у [https://www.wikidata.org/wiki/Q649 Москвы] указано сразу два объекта "495" и "499" у предиката P473, поэтому вернутся 2 результата, а не один. В SQL пришлось бы писать JOIN на ровном месте, а в SPARQL его нет вообще. | ||
[http://tinyurl.com/ | [http://tinyurl.com/qdwezf5 Открыть на query.wikidata.org] | ||
<syntaxhighlight lang="sql" line> | <syntaxhighlight lang="sql" line> | ||
SELECT ?item ?relationid ?itemLabel ?localdialingcode WHERE { | SELECT ?item ?relationid ?itemLabel ?countrydialingcode ?localdialingcode WHERE { | ||
?item wdt:P17 wd:Q159. | ?item wdt:P17 wd:Q159. | ||
?item wdt:P31 wd:Q515. | ?item wdt:P31 wd:Q515. | ||
Строка 62: | Строка 101: | ||
} | } | ||
?item wdt:P473 ?localdialingcode. | ?item wdt:P473 ?localdialingcode. | ||
wd:Q159 wdt:P474 ?countrydialingcode. | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Объекты-побратимы всех | === Объекты-побратимы всех российских объектов и их страны === | ||
Этот пример призван показать всю простоту JOIN-ов в SPARQL. | Этот пример призван показать всю простоту JOIN-ов в SPARQL. | ||
Строка 73: | Строка 113: | ||
Более того, в отличие от реляционных подходов, мы избавлены от вопросов: "в какой именно таблице хранятся города", "в какой таблице хранится информация о побратимстве". Сложность отличий нормальных форм не сбрасывается сразу на пользователя на уровне языка запросов. Необходимость в тщательном дизайне баз данных (таблиц и отношений) тоже уменьшается (по сравнению с табличным подходом и SQL). | Более того, в отличие от реляционных подходов, мы избавлены от вопросов: "в какой именно таблице хранятся города", "в какой таблице хранится информация о побратимстве". Сложность отличий нормальных форм не сбрасывается сразу на пользователя на уровне языка запросов. Необходимость в тщательном дизайне баз данных (таблиц и отношений) тоже уменьшается (по сравнению с табличным подходом и SQL). | ||
Составители запросов | Составители SPARQL-запросов просто исследуют данные запросами, а не думают постоянно, где именно эти данные расположены и как именно они связаны между собой. | ||
* Строка 2 | * Строка 2: [https://www.wikidata.org/wiki/Q2366010 Академический район] будет выбран как находящийся в России. | ||
* Строка 7: | * Строка 4: [https://www.wikidata.org/wiki/Q33349 Мелитополь] (Украина) будет выбран как побратим Академического района. | ||
* Строка 7: Исключаем исторические страны у городов-побратимов в результатах | |||
[https://query.wikidata.org/#SELECT%20DISTINCT%20%3FwikidataCity%20%3FrussianPlace%20%3Fcountry%20WHERE%20%7B%0A%20%20%3FrussianPlace%20wdt%3AP17%20wd%3AQ159%20.%0A%20%20%0A%20%20%3FrussianPlace%20wdt%3AP190%20%3FwikidataCity%20.%0A%20%20%3FwikidataCity%20wdt%3AP17%20%3Fcountry%20.%0A%20%20%0A%20%20FILTER%20NOT%20EXISTS%20%7B%3Fcountry%20wdt%3AP31%20wd%3AQ3024240%7D%0A%7D%0AORDER%20BY%20%3FrussianPlace%20%3Fcountry Открыть на query.wikidata.org] | [https://query.wikidata.org/#SELECT%20DISTINCT%20%3FwikidataCity%20%3FrussianPlace%20%3Fcountry%20WHERE%20%7B%0A%20%20%3FrussianPlace%20wdt%3AP17%20wd%3AQ159%20.%0A%20%20%0A%20%20%3FrussianPlace%20wdt%3AP190%20%3FwikidataCity%20.%0A%20%20%3FwikidataCity%20wdt%3AP17%20%3Fcountry%20.%0A%20%20%0A%20%20FILTER%20NOT%20EXISTS%20%7B%3Fcountry%20wdt%3AP31%20wd%3AQ3024240%7D%0A%7D%0AORDER%20BY%20%3FrussianPlace%20%3Fcountry Открыть на query.wikidata.org] | ||
Строка 94: | Строка 135: | ||
В отличие от OpenStreetMap, Wikidata не ограничен "существующими прямо сейчас" объектами. Это можно использовать как хороший пример исключения из результатов. | В отличие от OpenStreetMap, Wikidata не ограничен "существующими прямо сейчас" объектами. Это можно использовать как хороший пример исключения из результатов. | ||
* 5 строка: исключаем<ref>https://www.w3.org/TR/sparql11-query/#negation</ref> те страны, которые - исторические | * 5 строка: исключаем<ref>https://www.w3.org/TR/sparql11-query/#negation</ref> те страны, которые - исторические | ||
* 10 строка: результаты упорядочены<ref>https://www.w3.org/TR/sparql11-query/#solutionModifiers</ref> по названиям на русском или английском | * 10 строка: результаты упорядочены<ref>https://www.w3.org/TR/sparql11-query/#solutionModifiers</ref> по названиям на русском или английском языках. | ||
[https://query.wikidata.org/#SELECT%20DISTINCT%20%3Fcountry%20%3FcountryLabel%20%3Fcapital%20%3FcapitalLabel%0AWHERE%0A%7B%0A%20%20%3Fcountry%20wdt%3AP31%20wd%3AQ3624078%20.%0A%20%20FILTER%20NOT%20EXISTS%20%7B%3Fcountry%20wdt%3AP31%20wd%3AQ3024240%7D%0A%20%20OPTIONAL%20%7B%20%3Fcountry%20wdt%3AP36%20%3Fcapital%20%7D%20.%0A%0A%20%20SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22ru%22%2C%20%22en%22%20%7D%0A%7D%0AORDER%20BY%20%3FcountryLabel Открыть на query.wikidata.org] | [https://query.wikidata.org/#SELECT%20DISTINCT%20%3Fcountry%20%3FcountryLabel%20%3Fcapital%20%3FcapitalLabel%0AWHERE%0A%7B%0A%20%20%3Fcountry%20wdt%3AP31%20wd%3AQ3624078%20.%0A%20%20FILTER%20NOT%20EXISTS%20%7B%3Fcountry%20wdt%3AP31%20wd%3AQ3024240%7D%0A%20%20OPTIONAL%20%7B%20%3Fcountry%20wdt%3AP36%20%3Fcapital%20%7D%20.%0A%0A%20%20SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22ru%22%2C%20%22en%22%20%7D%0A%7D%0AORDER%20BY%20%3FcountryLabel Открыть на query.wikidata.org] | ||
Строка 110: | Строка 151: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Города примерно с таким же населением как | === Города примерно с таким же населением, как Пермь === | ||
Города, отличающиеся от [https://www.wikidata.org/wiki/Q915 Перми] менее чем на 1000 человек по численности населения. | |||
[https://query.wikidata.org/#%23defaultView%3AMap%0ASELECT%20DISTINCT%20%3Fcity%20%3FcityLabel%20%3Fpopulatie2%20%3Fcoor%20WHERE%20%7B%0A%20%20wd%3AQ915%20wdt%3AP1082%20%3Fpopulatie%20.%0A%20%20%3Fcity%20wdt%3AP1082%20%3Fpopulatie2%20 | * 6 строка: abs<ref>https://www.w3.org/TR/sparql11-query/#func-abs</ref> это одна из множества возможных ''функций на числах'' в ''тестовых выражениях'' и ''фильтрах''<ref>https://www.w3.org/TR/sparql11-query/#expressions</ref> | ||
[https://query.wikidata.org/#%23defaultView%3AMap%0ASELECT%20DISTINCT%20%3Fcity%20%3FcityLabel%20%3Fpopulatie2%20%3Fcoor%20WHERE%20%7B%0A%20%20wd%3AQ915%20wdt%3AP1082%20%3Fpopulatie%20.%0A%20%20%3Fcity%20wdt%3AP1082%20%3Fpopulatie2%20.%0A%20%20%3Fcity%20wdt%3AP625%20%3Fcoor%20.%0A%20%20FILTER%20%28abs%28%3Fpopulatie%20-%20%3Fpopulatie2%29%20%3C%201000%29%0A%20%20SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22ru%2Cen%22%20%7D%0A%7D Открыть на query.wikidata.org] | |||
<syntaxhighlight lang="sql" line> | <syntaxhighlight lang="sql" line> | ||
#defaultView:Map | #defaultView:Map | ||
SELECT DISTINCT ?city ?cityLabel ?populatie2 ?coor WHERE { | SELECT DISTINCT ?city ?cityLabel ?populatie2 ?coor WHERE { | ||
wd:Q915 wdt:P1082 ?populatie . | wd:Q915 wdt:P1082 ?populatie . | ||
?city wdt:P1082 ?populatie2 | ?city wdt:P1082 ?populatie2 . | ||
?city wdt:P625 ?coor . | |||
FILTER (abs(?populatie - ?populatie2) < 1000) | FILTER (abs(?populatie - ?populatie2) < 1000) | ||
SERVICE wikibase:label { bd:serviceParam wikibase:language "ru,en" } | SERVICE wikibase:label { bd:serviceParam wikibase:language "ru,en" } | ||
} | } | ||
</syntaxhighlight> | |||
=== Ранжирование городов по населению === | |||
* Строка 10-17: BIND-конструкция<ref>https://www.w3.org/TR/sparql11-query/#assignment</ref> позволяет создать переменную и присвоить ей значение. В данном примере мы использовали другую переменную (?population), чтобы создать новую (?layer) | |||
* Строка 11: первый из 5 вложенных в "хвостовую часть" IF (условие, значение при истине, значение при не истине) | |||
[https://query.wikidata.org/#%23defaultView%3AMap%0ASELECT%20DISTINCT%20%3Fcity%20%3FcityLabel%20%3Fpopulation%20%3Flayer%20%3Fcoordinates%20WHERE%20%7B%0A%20%20%3Fcity%20wdt%3AP17%20wd%3AQ159.%0A%20%20%3Fcity%20wdt%3AP31%20wd%3AQ515.%0A%0A%20%20OPTIONAL%20%7B%20%3Fcity%20wdt%3AP1082%20%3Fpopulation.%20%7D%0A%20%20%0A%20%20%3Fcity%20wdt%3AP625%20%3Fcoordinates.%0A%20%20%0A%20%20BIND%28%0A%20%20%20%20IF%28%3Fpopulation%20%3C%20500%2C%20%22500%22%2C%0A%20%20%20%20IF%28%3Fpopulation%20%3C%2010000%2C%20%2210K%22%2C%0A%20%20%20%20IF%28%3Fpopulation%20%3C%20100000%2C%20%22100K%22%2C%0A%20%20%20%20IF%28%3Fpopulation%20%3C%201000000%2C%20%221M%22%2C%0A%20%20%20%20IF%28%3Fpopulation%20%3C%2010000000%2C%20%2210M%22%2C%0A%20%20%20%20%22%3E20M%22%29%29%29%29%29%0A%20%20%20%20AS%20%3Flayer%29.%0A%0A%20%20SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22ru%2Cen%22%20%7D%0A%7D%0AORDER%20BY%20%0ADESC%28%3Fpopulation%29 Открыть на query.wikidata.org] | |||
<syntaxhighlight lang="sql" line> | |||
#defaultView:Map | |||
SELECT DISTINCT ?city ?cityLabel ?population ?layer ?coordinates WHERE { | |||
?city wdt:P17 wd:Q159. | |||
?city wdt:P31 wd:Q515. | |||
OPTIONAL { ?city wdt:P1082 ?population. } | |||
?city wdt:P625 ?coordinates. | |||
BIND( | |||
IF(?population < 500, "500", | |||
IF(?population < 10000, "10K", | |||
IF(?population < 100000, "100K", | |||
IF(?population < 1000000, "1M", | |||
IF(?population < 10000000, "10M", | |||
">20M"))))) | |||
AS ?layer). | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "ru,en" } | |||
} | |||
ORDER BY | |||
DESC(?population) | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Строка 150: | Строка 224: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Города, которые | === Города, которые соединяются Транссибирской магистралью или Трансмонгольской железной дорогой === | ||
* 5 строка: конструкция VALUES<ref>https://www.w3.org/TR/sparql11-query/#inline-data</ref> используется чтобы вручную указать значения у отдельных элементов | * 5 строка: конструкция VALUES<ref>https://www.w3.org/TR/sparql11-query/#inline-data</ref> используется чтобы вручную указать значения у отдельных элементов | ||
[https://query.wikidata.org/#%23defaultView%3AMap%0ASELECT%20%3Fcity%20%3FcityLabel%20%3Fcoordinates%0AWHERE%0A%7B%0A%20%20%20VALUES%20%3Fhighway%20%7B%20wd%3AQ559037%20wd%3AQ58767%20%7D%20%0A%20%20%20%3Fhighway%20wdt%3AP2789%20%3Fcity%20.%0A%20%20%20%20%3Fcity%20wdt%3AP625%20%3Fcoordinates%20.%0A%20%20%20SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22ru%2Cen%22.%20%7D%0A%7D Открыть на query.wikidata.org] | [https://query.wikidata.org/#%23defaultView%3AMap%0ASELECT%20%3Fcity%20%3FcityLabel%20%3Fcoordinates%0AWHERE%0A%7B%0A%20%20%20VALUES%20%3Fhighway%20%7B%20wd%3AQ559037%20wd%3AQ58767%20%7D%20%0A%20%20%20%3Fhighway%20wdt%3AP2789%20%3Fcity%20.%0A%20%20%20%20%3Fcity%20wdt%3AP625%20%3Fcoordinates%20.%0A%20%20%20SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22ru%2Cen%22.%20%7D%0A%7D Открыть на query.wikidata.org] | ||
Строка 165: | Строка 239: | ||
?city wdt:P625 ?coordinates . | ?city wdt:P625 ?coordinates . | ||
SERVICE wikibase:label { bd:serviceParam wikibase:language "ru,en". } | SERVICE wikibase:label { bd:serviceParam wikibase:language "ru,en". } | ||
} | |||
</syntaxhighlight> | |||
== Wikidata-префиксы == | |||
[https://www.mediawiki.org/wiki/Wikibase/Indexing/RDF_Dump_Format#Full_list_of_prefixes Полный список префиксов]. | |||
=== Квалификаторы (qualifier) === | |||
Если открыть [https://www.wikidata.org/wiki/Q915 Пермь], то там указанно множество значений у численности населения (P1082), причём все значения — одного ранга (нормальный). | |||
У некоторых из значений численности населения указаны [https://www.wikidata.org/wiki/Help:Qualifiers/ru квалификаторы] (qualifier) P585 (момент времени) и P459 (метод определения). | |||
* 2 строка: будут выбраны все 43 высказывания у элемента Q915 и свойства P1082 | |||
* 3 строка: выбираем их значения | |||
* 4-5 строка: выбираем нужные квалификаторы. | |||
[https://query.wikidata.org/#SELECT%20%3Fvalue%20%3Fqualifier%20%3Fwikidataid%20WHERE%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20wd%3AQ915%20p%3AP1082%20%3Fstatements%20%20%20%20%20%20%20%20%20%20%20.%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Fstatements%20ps%3AP1082%20%3Fvalue%20%20%20%20%20%20.%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Fstatements%20pq%3AP585%20%20%3Fqualifier%20%20.%0A%20OPTIONAL%20%7B%20%3Fstatements%20pq%3AP459%20%20%3Fwikidataid%20.%20%7D%0A%7D Открыть на query.wikidata.org] | |||
<syntaxhighlight lang="sql" line> | |||
SELECT ?val ?qualifier ?wikidataid WHERE { | |||
wd:Q915 p:P1082 ?statements . | |||
?statements ps:P1082 ?val . | |||
?statements pq:P585 ?qualifier . | |||
OPTIONAL { ?statements pq:P459 ?wikidataid . } | |||
} | |||
</syntaxhighlight> | |||
=== Ранг (rank) === | |||
Показать все страны, относящиеся (и относившиеся ранее) к Перми, и их [https://www.wikidata.org/wiki/Help:Ranking/ru ранги]. | |||
[https://query.wikidata.org/#SELECT%20DISTINCT%20%3FdoLabel%20%3Fdo%20%3Frank%20WHERE%20%7B%0A%23%20%20VALUES%20%3Frank%20%7B%20wikibase%3ADeprecatedRank%20wikibase%3ANormalRank%20wikibase%3APreferredRank%20%7D%0A%20%20%20%20wd%3AQ915%20%20%20%20%20%20%20p%3AP17%20%3Fvalue.%0A%20%20%20%20%3Fvalue%20%20%20%20%20%20%20ps%3AP17%20%3Fdo%20.%0A%20%20%20%20%3Fvalue%20wikibase%3Arank%20%3Frank%20.%0A%20%20%0A%20%20%20SERVICE%20wikibase%3Alabel%20%7B%0A%20%20%20%20%20bd%3AserviceParam%20wikibase%3Alanguage%20%22ru%22%20.%0A%20%20%20%7D%0A%7D Открыть на query.wikidata.org] | |||
<syntaxhighlight lang="sql" line> | |||
SELECT DISTINCT ?doLabel ?do ?rank WHERE { | |||
# VALUES ?rank { wikibase:DeprecatedRank wikibase:NormalRank wikibase:PreferredRank } | |||
wd:Q915 p:P17 ?value. | |||
?value ps:P17 ?do . | |||
?value wikibase:rank ?rank . | |||
SERVICE wikibase:label { | |||
bd:serviceParam wikibase:language "ru" . | |||
} | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Строка 178: | Строка 293: | ||
* [https://query.wikidata.org/#SELECT%0A%09%3Fcountry%20%3FcountryLabel%0A%09%3FwikiPersons%0A%09%3Fpopulation%0A%09%28ROUND%28%3FwikiPersons%2F%3Fpopulation%2a1000000%29%20AS%20%3FwikiPersonsPerM%29%0AWHERE%0A%7B%0A%09%7B%20SELECT%20%3Fcountry%20%28count%28%2a%29%20as%20%3FwikiPersons%29%20WHERE%20%7B%0A%09%09%7BSELECT%20DISTINCT%20%3Fperson%20%3Fcountry%20WHERE%20%7B%0A%09%09%09%3Fcountry%20wdt%3AP31%20wd%3AQ185441%20.%0A%09%09%09%23%20BIND%28%20wd%3AQ30%20AS%20%3Fcountry%20%29%20%23%20use%20instead%20of%20previous%20line%20to%20check%20individual%20countries%0A%09%09%09%3Fperson%20wdt%3AP31%20wd%3AQ5%20.%0A%09%09%09%3Fperson%20wdt%3AP27%20%3Fcountry%20.%0A%09%09%09FILTER%20NOT%20EXISTS%7B%20%3Fperson%20wdt%3AP570%20%3Fdate%20%7D%20%23%20only%20count%20living%20people%0A%09%09%7D%20%7D%0A%09%7D%20GROUP%20BY%20%3Fcountry%20%20%7D%0A%09%3Fcountry%20wdt%3AP1082%20%3Fpopulation%0A%09SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22ru%22%20%7D%0A%7D%0AORDER%20BY%20DESC%28%3FwikiPersonsPerM%29 Количество записей о людях в Викиданных на каждый миллион населения в данной стране] | * [https://query.wikidata.org/#SELECT%0A%09%3Fcountry%20%3FcountryLabel%0A%09%3FwikiPersons%0A%09%3Fpopulation%0A%09%28ROUND%28%3FwikiPersons%2F%3Fpopulation%2a1000000%29%20AS%20%3FwikiPersonsPerM%29%0AWHERE%0A%7B%0A%09%7B%20SELECT%20%3Fcountry%20%28count%28%2a%29%20as%20%3FwikiPersons%29%20WHERE%20%7B%0A%09%09%7BSELECT%20DISTINCT%20%3Fperson%20%3Fcountry%20WHERE%20%7B%0A%09%09%09%3Fcountry%20wdt%3AP31%20wd%3AQ185441%20.%0A%09%09%09%23%20BIND%28%20wd%3AQ30%20AS%20%3Fcountry%20%29%20%23%20use%20instead%20of%20previous%20line%20to%20check%20individual%20countries%0A%09%09%09%3Fperson%20wdt%3AP31%20wd%3AQ5%20.%0A%09%09%09%3Fperson%20wdt%3AP27%20%3Fcountry%20.%0A%09%09%09FILTER%20NOT%20EXISTS%7B%20%3Fperson%20wdt%3AP570%20%3Fdate%20%7D%20%23%20only%20count%20living%20people%0A%09%09%7D%20%7D%0A%09%7D%20GROUP%20BY%20%3Fcountry%20%20%7D%0A%09%3Fcountry%20wdt%3AP1082%20%3Fpopulation%0A%09SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22ru%22%20%7D%0A%7D%0AORDER%20BY%20DESC%28%3FwikiPersonsPerM%29 Количество записей о людях в Викиданных на каждый миллион населения в данной стране] | ||
== | Более сложные примеры: https://bitbucket.org/sulab/wikidatasparqlexamples | ||
== Альтернативы SPARQL у Wikidata == | |||
Нужно отметить, что SPARQL подразумевает только запросы на чтение. Часть языка на обновление, добавление и удаление данных — [https://www.w3.org/TR/2013/REC-sparql11-update-20130321/ SPARQL 1.1 Update] — в данной статье не рассматривалась. | |||
Для доступа на запись вам необходимо ознакомиться с короткой [https://www.wikidata.org/wiki/Wikidata:Bots процедурой регистрации ботов] и [https://www.wikidata.org/wiki/Wikidata:Requests_for_permissions/Bot отправить заявку участника-ботовода]. | |||
# [https://www.npmjs.com/package/wikidata-cli wikidata-cli] | |||
# [https://github.com/maxlath/wikidata-sdk wikidata-sdk] | |||
# Wikidata API. Заявления у Q915: [https://www.wikidata.org/w/api.php?action=wbgetentities&format=json&ids=Q915 в JSON] или [https://www.wikidata.org/w/api.php?action=wbgetentities&format=xml&ids=Q915 в XML] | |||
# [https://github.com/jcreus/pywikidata pywikidata] - проект для доступа и на чтение и запись к элементам Wikidata. [https://www.wikidata.org/wiki/Wikidata:Creating_a_bot руководство по созданию ботов] и [https://www.mediawiki.org/wiki/Manual:Pywikibot/Scripts#Wikidata примеры скриптов миграции данных из Википедии и Wikidata]. | |||
== Источники == | |||
<references/> | <references/> | ||
== Внешние ссылки == | |||
* [https://www.wikidata.org/wiki/Help:Contents/ru Справочный портал Wikidata] | |||
* [https://virtuoso.openlinksw.com/tutorials/sparql/ Обучающие материалы OpenLink Software о SPARQL] - части [https://virtuoso.openlinksw.com/tutorials/sparql/SPARQL_Tutorials_Part_10/SPARQL_Tutorials_Part_10.html 10] и [https://virtuoso.openlinksw.com/tutorials/sparql/SPARQL_Tutorials_Part_11/SPARQL_Tutorials_Part_11.html 11] покрывают основы GeoSPARQL |
Текущая версия от 11:27, 28 ноября 2016
по адресу http://gis-lab.info/qa/sparql_wikidata.html
SPARQL — это язык запросов к данным, основанных на модели "субъект-предикат-объект" (примечание: "объект" часто заменяется на "значение", особенно в случае количественных предикатов) (в терминах Wikidata элемент-свойство-значения, item-property-values). Wikidata — открытый проект, потенциально интересный в гео-проектах и доступный в виде публичной SPARQL-точки
Инструментарий запросов
Запросы к Wikidata можно составлять с помощью различных SPARQL-клиентов. Ключевая особенность Wikidata — это общедоступная и публичная точка доступа SPARQL, включающая в том числе простой веб-интерфейс.
query.wikidata.org
У сервиса query.wikidata.org есть целое руководство на английском языке https://www.mediawiki.org/wiki/Wikidata_query_service/User_Manual и репозиторий для разработчиков https://github.com/wikimedia/wikidata-query-rdf.
Обратите внимание, что результаты запросов можно скачать в формате CSV — хорошее подспорье для более серьёзной работы при помощи других инструментов.
В таблице результатов (в нижней части экрана) можно отфильтровать результаты, используя поиск по всем полям сразу (например, можно попробовать найти "Moscow").
Wikidata
Для помощи по терминологии и модели Wikidata можно посмотреть сюда: Викиданные:Глоссарий.
Структуру элемента (item) и свойства (property) можно найти на англоязычной странице Wikibase/DataModel/Primer.
- Множественные значения
- Отсутствующие значения (известно, что значения не может быть) эквивалентны тегам ключ=no из OpenStreetMap - описаны на странице Help:Утверждения
- Значение не определено (известно, что значение есть, но не известно какое) - описаны на той же странице
Диаграмма русскоязычной терминологии утверждений в Викиданных
Свойства Wikidata
Полный перечень свойств: Wikidata:List_of_properties
Отчёт количества использований каждого свойства - Wikidata:Database_reports/List_of_properties/all
- дата прекращения существования - https://www.wikidata.org/wiki/Property:P576
- дата окончания - https://www.wikidata.org/wiki/Property:P582
Географические свойства в Wikidata
Полный перечень: Wikidata:List_of_properties/Geographical_feature
- Принадлежность стране - https://www.wikidata.org/wiki/Property:P17
- Принадлежность админ делению - https://www.wikidata.org/wiki/Property:P131
- Координаты (точка) - https://www.wikidata.org/wiki/Property:P625 (при выборке этого свойства появляется возможность представить результаты на карте в нижней части экрана)
- Численность населения - https://www.wikidata.org/wiki/Property:P1082
- ID отношения из OpenStreetMap - https://www.wikidata.org/wiki/Property:P402
- Столица - https://www.wikidata.org/wiki/Property:P36
- Город-побратим - https://www.wikidata.org/wiki/Property:P190
- Относительная высота https://www.wikidata.org/wiki/Property:P2660
- Официальный язык - https://www.wikidata.org/wiki/Property:P37
Российские свойства в Wikidata
- код ОКАТО https://www.wikidata.org/wiki/Property:P721
- код ОКТМО https://www.wikidata.org/wiki/Property:P764
- Портал «Герои страны» ID https://www.wikidata.org/wiki/Property:P2943
Географические элементы в Wikidata
- континент - https://www.wikidata.org/wiki/Q5107
- суверенное государство - https://www.wikidata.org/wiki/Q3624078
- историческое государство - https://www.wikidata.org/wiki/Q3024240
- город - https://www.wikidata.org/wiki/Q515
- Северный полюс - https://www.wikidata.org/wiki/Q934
- Южный полюс - https://www.wikidata.org/wiki/Q933
Wikidata Blazegraph
Blazegraph — расширение от Wikidata к Blazegraph, чтобы сделать запросы к Wikibase более эффективными. Имеет лицензию GPLv2.
- Функция geof:distance возвращает минимальное расстояние между двумя точками.
Элементы SPARQL-запросов
Т.к. исходные данные представляют граф (элемент-свойство-значения) и его модификации (в Wikidata: квалификаторы, ссылки и др.), то большинство SPARQL-запросов строятся вокруг поиска паттернов в графе[1], зачастую нескольких.
Города в России с телефонными кодами
Самый простой пример.
- 1 строка: SELECT запросы[2] выбирают данные или их часть
- 2 строка: выбираем субъекты (?item), у которых явно указано, что они в стране - Россия (Q159)
- 3 строка: выбираем субъекты (?item), у которых явно указано, что они суть - города (Q515)
- 4-6 строка: т.к. значения предиката "ID отношения из OpenStreetMap" P402 могут быть просто не заполнены у отдельных объектов, такие объекты будут исключены из результатов. Это не совсем интуитивно понятно для людей, привыкших к SQL-запросам (где NULL-значения возвращаются в большинстве случаев). В SPARQL необязательные значения[3] нужно включать в результаты вручную.
- 7 строка: выбираем все возможные субъекты и объекты у предиката P473 (код города). Примечание о части "?localdialingcode": в Wikidata у Москвы указано сразу два объекта "495" и "499" у предиката P473, поэтому вернутся 2 результата, а не один. В SQL пришлось бы писать JOIN на ровном месте, а в SPARQL его нет вообще.
SELECT ?item ?relationid ?itemLabel ?countrydialingcode ?localdialingcode WHERE {
?item wdt:P17 wd:Q159.
?item wdt:P31 wd:Q515.
OPTIONAL {
?item wdt:P402 ?relationid.
}
?item wdt:P473 ?localdialingcode.
wd:Q159 wdt:P474 ?countrydialingcode.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
Объекты-побратимы всех российских объектов и их страны
Этот пример призван показать всю простоту JOIN-ов в SPARQL.
Для подходящего первичного ключа (в реляционных терминах) было достаточно найти только сам предикат (город-побратим).
Более того, в отличие от реляционных подходов, мы избавлены от вопросов: "в какой именно таблице хранятся города", "в какой таблице хранится информация о побратимстве". Сложность отличий нормальных форм не сбрасывается сразу на пользователя на уровне языка запросов. Необходимость в тщательном дизайне баз данных (таблиц и отношений) тоже уменьшается (по сравнению с табличным подходом и SQL).
Составители SPARQL-запросов просто исследуют данные запросами, а не думают постоянно, где именно эти данные расположены и как именно они связаны между собой.
- Строка 2: Академический район будет выбран как находящийся в России.
- Строка 4: Мелитополь (Украина) будет выбран как побратим Академического района.
- Строка 7: Исключаем исторические страны у городов-побратимов в результатах
SELECT DISTINCT ?wikidataCity ?russianPlace ?country WHERE {
?russianPlace wdt:P17 wd:Q159 .
?russianPlace wdt:P190 ?wikidataCity .
?wikidataCity wdt:P17 ?country .
FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240}
}
ORDER BY ?russianPlace ?country
Существующие страны и их столицы
В отличие от OpenStreetMap, Wikidata не ограничен "существующими прямо сейчас" объектами. Это можно использовать как хороший пример исключения из результатов.
- 5 строка: исключаем[4] те страны, которые - исторические
- 10 строка: результаты упорядочены[5] по названиям на русском или английском языках.
SELECT DISTINCT ?country ?countryLabel ?capital ?capitalLabel
WHERE
{
?country wdt:P31 wd:Q3624078 .
FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240}
OPTIONAL { ?country wdt:P36 ?capital } .
SERVICE wikibase:label { bd:serviceParam wikibase:language "ru", "en" }
}
ORDER BY ?countryLabel
Города примерно с таким же населением, как Пермь
Города, отличающиеся от Перми менее чем на 1000 человек по численности населения.
- 6 строка: abs[6] это одна из множества возможных функций на числах в тестовых выражениях и фильтрах[7]
#defaultView:Map
SELECT DISTINCT ?city ?cityLabel ?populatie2 ?coor WHERE {
wd:Q915 wdt:P1082 ?populatie .
?city wdt:P1082 ?populatie2 .
?city wdt:P625 ?coor .
FILTER (abs(?populatie - ?populatie2) < 1000)
SERVICE wikibase:label { bd:serviceParam wikibase:language "ru,en" }
}
Ранжирование городов по населению
- Строка 10-17: BIND-конструкция[8] позволяет создать переменную и присвоить ей значение. В данном примере мы использовали другую переменную (?population), чтобы создать новую (?layer)
- Строка 11: первый из 5 вложенных в "хвостовую часть" IF (условие, значение при истине, значение при не истине)
#defaultView:Map
SELECT DISTINCT ?city ?cityLabel ?population ?layer ?coordinates WHERE {
?city wdt:P17 wd:Q159.
?city wdt:P31 wd:Q515.
OPTIONAL { ?city wdt:P1082 ?population. }
?city wdt:P625 ?coordinates.
BIND(
IF(?population < 500, "500",
IF(?population < 10000, "10K",
IF(?population < 100000, "100K",
IF(?population < 1000000, "1M",
IF(?population < 10000000, "10M",
">20M")))))
AS ?layer).
SERVICE wikibase:label { bd:serviceParam wikibase:language "ru,en" }
}
ORDER BY
DESC(?population)
Бывшие столицы государств
#defaultView:Map
SELECT DISTINCT ?country ?countryLabel ?capital ?capitalLabel ?coordinates ?ended
WHERE
{
?country p:P36 ?stat.
?stat ps:P36 ?capital.
?capital wdt:P625 ?coordinates.
OPTIONAL {
?country wdt:P582|wdt:P576 ?ended.
}
OPTIONAL {
?capital wdt:P582|wdt:P576 ?ended.
}
OPTIONAL {
?stat pq:P582 ?ended.
}
FILTER(BOUND(?ended)).
SERVICE wikibase:label { bd:serviceParam wikibase:language "ru,en". }
}
Города, которые соединяются Транссибирской магистралью или Трансмонгольской железной дорогой
- 5 строка: конструкция VALUES[9] используется чтобы вручную указать значения у отдельных элементов
#defaultView:Map
SELECT ?city ?cityLabel ?coordinates
WHERE
{
VALUES ?highway { wd:Q559037 wd:Q58767 }
?highway wdt:P2789 ?city .
?city wdt:P625 ?coordinates .
SERVICE wikibase:label { bd:serviceParam wikibase:language "ru,en". }
}
Wikidata-префиксы
Квалификаторы (qualifier)
Если открыть Пермь, то там указанно множество значений у численности населения (P1082), причём все значения — одного ранга (нормальный).
У некоторых из значений численности населения указаны квалификаторы (qualifier) P585 (момент времени) и P459 (метод определения).
- 2 строка: будут выбраны все 43 высказывания у элемента Q915 и свойства P1082
- 3 строка: выбираем их значения
- 4-5 строка: выбираем нужные квалификаторы.
SELECT ?val ?qualifier ?wikidataid WHERE {
wd:Q915 p:P1082 ?statements .
?statements ps:P1082 ?val .
?statements pq:P585 ?qualifier .
OPTIONAL { ?statements pq:P459 ?wikidataid . }
}
Ранг (rank)
Показать все страны, относящиеся (и относившиеся ранее) к Перми, и их ранги.
SELECT DISTINCT ?doLabel ?do ?rank WHERE {
# VALUES ?rank { wikibase:DeprecatedRank wikibase:NormalRank wikibase:PreferredRank }
wd:Q915 p:P17 ?value.
?value ps:P17 ?do .
?value wikibase:rank ?rank .
SERVICE wikibase:label {
bd:serviceParam wikibase:language "ru" .
}
}
Примеры запросов
Часть примеров:
- Все континенты из Wikidata, отсортированные по убыванию их Wikidata идентификатора
- Объекты в более чем 3000 км от южного полюса, но всё ещё относящиеся к Антарктике
- Страны по убыванию населения
- Самый населённый город в каждой стране
- Количество записей о людях в Викиданных на каждый миллион населения в данной стране
Более сложные примеры: https://bitbucket.org/sulab/wikidatasparqlexamples
Альтернативы SPARQL у Wikidata
Нужно отметить, что SPARQL подразумевает только запросы на чтение. Часть языка на обновление, добавление и удаление данных — SPARQL 1.1 Update — в данной статье не рассматривалась.
Для доступа на запись вам необходимо ознакомиться с короткой процедурой регистрации ботов и отправить заявку участника-ботовода.
- wikidata-cli
- wikidata-sdk
- Wikidata API. Заявления у Q915: в JSON или в XML
- pywikidata - проект для доступа и на чтение и запись к элементам Wikidata. руководство по созданию ботов и примеры скриптов миграции данных из Википедии и Wikidata.
Источники
- ↑ https://www.w3.org/TR/sparql11-query/#GraphPattern
- ↑ https://www.w3.org/TR/sparql11-query/#QueryForms
- ↑ https://www.w3.org/TR/sparql11-query/#optionals
- ↑ https://www.w3.org/TR/sparql11-query/#negation
- ↑ https://www.w3.org/TR/sparql11-query/#solutionModifiers
- ↑ https://www.w3.org/TR/sparql11-query/#func-abs
- ↑ https://www.w3.org/TR/sparql11-query/#expressions
- ↑ https://www.w3.org/TR/sparql11-query/#assignment
- ↑ https://www.w3.org/TR/sparql11-query/#inline-data
Внешние ссылки
- Справочный портал Wikidata
- Обучающие материалы OpenLink Software о SPARQL - части 10 и 11 покрывают основы GeoSPARQL