JA:Sophox

From OpenStreetMap Wiki
Jump to navigation Jump to search
始め方についての短いビデオ

Sophox はOSMデータ、OSMタグのメタデータ(ウィキより取得)、そしてWikidataのような外部の(連携した)データソースなどで作業するためのデータサービスの集まりです。このサービスではSPARQLと呼ばれるよく知られたSQLライクな言語を使います。このサービスはまた手動の「検索&編集」的なやり方やMapRouletteのようなチャレンジとして直接のOSM編集のために使うことができます。ウィキデータのSPARQL関連文書は全てWikidata Query Helpにあります。Overpass-Turboと同様に、このサービスはJOSM (Wikipedia pluginを有効化)から直接使うことができます。

短い始め方のビデオ(右側)は短いイントロです。「例」ボタンで https://sophox.org/ のサービスを試してみてください。

このサービスはElastic (of Elasticsearch fame)のご厚意によるハードウェアの寄付によって利用可能になっています。

重要な変更

領域やパフォーマンスの制限により、Sophox は現在はウィキデータのコピーを持っていません。ウィキデータのsparqlクエリーのエンドポイントを呼び出すには連携クエリーを使ってください。

現在のチャレンジ

Wikipedia Improvement Tasks参照

Hello (OSM SPARQL) World

SPARQL, Wikibase RDF format 及びOSM RDF formatを使ったシンプルな例です。このクエリーはOSMの場所オブジェクトを少し一覧化し、下部の「実行する」をクリックして実行することができます。(類似のOverpass Queryと比べてみてください)
OSMデータとウィキデータの相互参照については、ウィキペディアページの人気度や品質管理の実行その他のクエリーを使った、多数のquery examplesがあります。

# placeタグのあるOSMオブジェクトをすべて一覧表示するサンプルクエリー。
# * はWHERE 節で使われる全ての変数を表示します
SELECT * WHERE {
  # 最初の表現は以下のようにトリプルストアの3カラムに対応します:
  #   "OSMの'place'タグを持つ任意の主語とそのタグが持つ値を探す"
  #
  # 疑問符は変数を表します。?osmId はOSMオブジェクトへのURIになります。例:
  #    <https://www.openstreetmap.org/node/2681940767>  (エベレスト)
  # 同じURIは接頭辞を付けて書くこともできます - osmnode:2681940767
  # 全てのOSMタグはosmt: 接頭辞を使います。osmt:place という定数を使うとplaceタグ
  # を持つOSMオブジェクトだけに合致します。?place という変数はplaceタグの
  # 値になります。変数の代わりに定数を使えます。
  # 例: ?place を定数の文字列'city'で置き換えます。

  ?osmId osmt:place ?place .

  # osmm: 接頭辞は"メタ値"を意味します。例: OSMオブジェクトの種別, 位置(loc), バージョン, ...
  # 特定のOSMオブジェクト('n', 'r', 'w')に限定する場合は次の行のコメントを外してください。
  #   ?osmId osmm:type 'r' .

  # osmm:loc はたいていのOSMオブジェクトの中心点用です。これが含まれている場合は、マップビューに切り替えて
  # (クエリーのすぐ下)マップ上に表示できます
  #   ?osmId osmm:loc ?loc .

  # The FILTER の表現はシンプルな"完全一致"にとどまらず、複雑なフィルタリングができます。
  #   FILTER (?place = 'town' || regex(?place, '[a-z][0-9]', 'i'))

  # これは結果を`name:en` タグを持っていないplaceに制限します。
  #   FILTER NOT EXISTS { ?osmId osmt:name:en ?nameen . }

  # wikidataタグを持つOSMオブジェクトに対して、英語名を(もしそれがウィキデータ内にあれば)探します。
  # また、そのオブジェクトがどういった種別(P31 = クラス)なのか、そしてその種別用のラベルも、
  # (英語で登録されている場合に)取得します。ラベルと説明については、その代わりに
  # 一覧に従って最初の利用可能な言語を選び出すサービスを使うこともできます。
  #   ?osmId osmt:wikidata ?wd .
  #   ?wd wdt:P31 ?type .
  #   OPTIONAL { ?wd rdfs:label ?label .  FILTER (lang(?label) = "en") }
  #   OPTIONAL { ?type rdfs:label ?typelabel .  FILTER (lang(?typelabel) = "en") }
}
# SQLと同様に、クエリーではアグリゲーションやサブクエリーを使ったり、結果の数を制限したりできます
LIMIT 10

Run it (edit query)

JOSMからの利用

このサービスはJOSM editorから直接利用できます。

  • Wikipedia pluginをインストールしてexpert mode (view メニュー内)を有効化
  • ファイル / Download data / をSophox APIからダウンロードタブから利用。

JOSMはクエリー結果で見つかったすべてのOSMオブジェクトIDをダウンロードします。他の値は全て無視され、サーバー負荷軽減のためリクエストすべきではありません。クエリーを手助けする魔法のキーワードがいくつかあります:

  • {{boxParams}}: wikibase:box serviceとともに使います。マップで選択した結果はcornerWest 及び cornerEast パラメータ用の2つのパラメータに変換されます。
  • {{center}}: マップ選択の中心がポイントの定数として挿入されます。

例:

information sign

これらのクエリーはJOSMからのみ動作します。なぜなら{{*}} パラメータを使っているからです。
広いエリアで矩形のサービスのクエリーを使うと、特定の条件下での世界中のオブジェクトを取得するより遅くなることがよくあります

OSMオブジェクトは人間ではありませんが、人間はその主題になることができるので、subject:wikidataが使われるでしょう。このクエリーは選択されたエリア内のwikidataタグでタグ付けされたオブジェクトを見つけます。このクエリーは広域で使われるととても遅くなります。

# 選ばれたエリア内で人間としてタグ付けされたオブジェクトを探す(広域では時間が掛かります)
SELECT ?osmid WHERE {
  SERVICE wikibase:box {
    ?osmid osmm:loc ?location .
    {{boxParams}}
  }
  ?osmid osmt:wikidata ?wd .
  ?wd wdt:P31/wdt:P279* wd:Q5 .
}

このクエリーは選択された中心ポイントの周囲にリングを形成するオブジェクトを見つけるためにシンプルな計算とフィルターを使います。

# 選択した中心点から2-3kmにある教育機関を探します
SELECT ?osmid WHERE {
  VALUES ?amenity { "kindergarten" "school" "university" "college" }
  ?osmid osmt:amenity ?amenity ;
         osmm:loc ?loc .
  BIND(geof:distance({{center}}, ?loc) as ?distance)
  FILTER(?distance > 2 && ?distance < 3)
}

上と同じですが"wikibase:around"サービスを使っています。

# 選択した中心点から2-3km以内にある教育機関を探します
SELECT ?osmid WHERE {
  VALUES ?amenity { "kindergarten" "school" "university" "college" }
  ?osmid osmt:amenity ?amenity .
  SERVICE wikibase:around { 
      ?osmid osmm:loc ?loc . 
      bd:serviceParam wikibase:center {{center}} . 
      bd:serviceParam wikibase:radius "3" . 
      bd:serviceParam wikibase:distance ?distance .
  } 
  FILTER(?distance > 2)
}

OSMデータの格納方法

全てのデータはトリプルストア主語 述語 目的語の文として格納されます。例えば、リレーション #123 は "name"というタグを持ち"値"をセットしますという文は、主語 (relation #123), 述語 ("name"というタグ), そして 目的語 ("値")と表すことができます。主語と述語の部分は必ず完全なURIでなけれななりません。例:<https://www.openstreetmap.org/way/42> (node #42), または <https://wiki.openstreetmap.org/wiki/Key:wikidata> (tag wikidata)。 URIをより読みやすくするために、短縮用の接頭辞を使います。例: osmway:42 およびosmt:wikidata。文の目的語の部分は値(string/number/boolean/geo coordinate/...)か、最初の2つの部分のようにURIでも構いません。このようにしてひとつの文の目的語(オブジェクト)は他の文の主語となることができ、リンクトグラフを作ります。SPARQLでは、各文はピリオドで終わらなければなりません。しかし複数の文が同じオブジェクトを持つ場合は、セミコロンで区切ります。接頭辞はエンジン内で定義されていますが、明確に手動で指定することもできます。

注意: 全てのRDF データは単一の巨大な "主語/述語/目的語" テーブルに格納されています。そのデータにはOSMデータ、このウィキからのOSMタグのメタデータ、ウィキペディアのページビューの統計、その他が含まれます。そのため主語にはosmnode:1234, osmd:Q42, サイトリンク、その他の種類のURIなどがあるでしょう。OSMオブジェクトだけを取得する一番簡単な方法はosmm:type 述語を使うことです - 全てのOSMオブジェクトにひとつあるでしょう。しかしパフォーマンス上の理由により、必要以上のフィルタは使わないようにしてください。- osmt:wikipedia,でOSMオブジェクトにクエリーをかける場合はosmm:typeを指定する必要はありません。なぜならosmt:wikipedia は既にOSMオブジェクトを含むからです。

osmnode:1234  osmm:type      'n'
osmnode:1234  osmm:loc       'Point(32.1 44.5)'^^geo:wktLiteral  # 経度/緯度
osmnode:1234  osmt:name      'ノードのnameタグ'
osmnode:1234  osmt:name:en   'ノードのname:enタグ'
osmnode:1234  osmt:wikipedia <https://en.wikipedia.org/wiki/Article_name>
osmnode:1234  osmt:wikidata  wd:Q34
 
osmway:2345  osmm:type       'w'
osmway:2345  osmm:loc        'Point(32.1 44.5)'^^geo:wktLiteral  # ウェイの中心点
osmway:2345  osmm:isClosed   true # このウェイがエリアかラインか
osmway:2345  osmt:name       'ウェイのnameタグ'
osmway:2345  osmt:name:en    'ウェイのname:enタグ'
osmway:2345  osmt:wikipedia  <https://en.wikipedia.org/wiki/Article_name>
osmway:2345  osmt:wikidata   wd:Q34
 
osmrel:3456  osmm:type       'r'
osmrel:3456  osmm:has        osmway:2345  # リレーションはウェイ#2345 を含む
osmrel:3456  osmway:2345     "inner"      # ウェイ #2345 には"inner" ロールがある
osmrel:3456  osmm:loc        'Point(32.1 44.5)'^^geo:wktLiteral  # メンバーの中心点
osmrel:3456  osmt:name       'ウェイのnameタグ'
osmrel:3456  osmt:name:en    'ウェイのname:enタグ'
osmrel:3456  osmt:wikipedia   <https://en.wikipedia.org/wiki/Article_name>
osmrel:3456  osmt:wikidata    wd:Q34


# 他のよくある値:
...  osmm:version    42         # 最後のオブジェクトのバージョン
...  osmm:changeset  1234567    # 変更セット内のこのオブジェクトの最後の編集
...  osmm:timestamp  '2017-08-23T01:02:03+00:00'^^xsd:dateTime    # 最後の編集時刻
...  osmm:user       'UserName' # ユーザー名 - 変更可能

その他のタグ:

  • osmm:badkey "@Sammelmütze" - あらゆる未サポートのタグ名が"osmm:badkey" オブジェクトとして、それ自身の値なしで格納されています。サポートされているタグに対しては、 /^[0-9a-zA-Z_]([-:0-9a-zA-Z_]*[0-9a-zA-Z_])?$/ という正規表現に合致しなければなりません。 -- ラテン文字、アラビア数字、およびアンダースコアだけを含みますダッシュ"-" とコロン":" は先頭と最後以外の位置以外で使うことができます。
  • osmm:loc:error "Error: ..." - ノードやウェイの位置が計算できないときは、このプロパティには関連するエラー情報が含まれます。

その他のデータソース

OSMメタデータ

キーやタグの説明のようにこのウィキのデータ項目も、例えばwd → osmd 及び wdt → osmdtのように少し異なる名前空間を使う点を除いてWikidata Query Serviceと同じ手法を使ってSophox内にインポートされます。こちらの優れた記事SPARQL wikibookを参照。

特別なosmd:Q... osmm:key osmt:...はデータ項目をOSMデータと結び付けるために自動的に追加されます。例えばbridge (Q103)osmd:Q103 osmm:key osmt:bridgeを持っています。

キー利用状況統計

全てのメタデータのキーはTaginfoからの利用統計を含んでいます。例えば, bridge (Q103) にはこれらの値がありTaginfo APIで定義されています:

osmd:Q103  osmm:count_all                 3621295  # OSMデータベース内でこのキーを持つオブジェクトの数。
osmd:Q103  osmm:count_all_fraction        0.0007   # Number of objects in relation to all objects.
osmd:Q103  osmm:count_nodes               4790     # OSMデータベース内でこのキーを持つノードの数。
osmd:Q103  osmm:count_nodes_fraction      0        # Number of nodes in relation to all tagged nodes.
osmd:Q103  osmm:count_relations           742      # Number of ways in the OSM database with this key.
osmd:Q103  osmm:count_relations_fraction  0.0001   # Number of ways in relation to all ways.
osmd:Q103  osmm:count_ways                3615763  # Number of relations in the OSM database with this key.
osmd:Q103  osmm:count_ways_fraction       0.0066   # Number of relations in relation to all relations.
osmd:Q103  osmm:users_all                 62161    # このキーのオブジェクトを所有するユーザーの数。
osmd:Q103  osmm:values_all                297      # このキーの異なる値の数。

Wikipedia ページビューのカウンター

もっとも人気のあるページにはSophox内に格納されているページビューのカウンターがあり、指定されたウィキ内の人気度で結果を並べることができます。カウントそのものには意味は無く、他のページビューとの比較としてのものです。このようにしてラベル付けのために都市間の重要性や特色を見ることができます。

  • <https://en.wikipedia.org/wiki/Universe> pageviews: 12345

外部データソース

Sophox クエリーは外部ソースからデータを引き出し、他のデータと組み合わせるでしょう。データは"表"形式(例:CSV)で、URL (例:Gistに格納されたものなど)経由でアクセスできなければなりません。正確なデータ形式は追加パラメータで構成されていても構いません。

SELECT * WHERE {

  # このサービスは下記で、外部のデータを引き出します 
  SERVICE wikibase:tabular {
    # データのURL: https://gist.github.com/nyurik/bc0e305248a66cfac565349e41f1ae99
    # "RAW" リンクを使用
    bd:serviceParam wikibase:url <https://gist.githubusercontent.com/nyurik/bc0e305248a66cfac565349e41f1ae99/raw/fbb0d844a8cb068faec9b90adecdae16e99da26f/museums-in-JC.csv> .

    # 私たちのデータにはヘッダー行が含まれ、"tabular:index"の代わりに"tabular:columnName"を使えます。
    bd:serviceParam wikibase:firstRowIsHeader true .

    # これらのカラムを取得して対応する名前付きの変数にセットします
    ?url tabular:url 'uri' .
    ?type tabular:type 'string' .
    ?id tabular:id 'integer' .
    ?name tabular:name 'string' .
  }
}

Run it (edit query)

Overpass 統合

Overpass サービスは[csv:...]と指示してCSV形式の結果を出力できます。あなたはOverpass Turboで「エクスポート」をクリックして「Overpass APIから抽出された生データ」のリンクからシンプルなデータURLを作成できます。これにより可読性が低いURLエンコードされたクエリー文字列が出力されます。代わりに、オリジナルのクエリーをotQueryパラメータとして使うこともできます。otQuery を指定するとタブ区切りの結果をパースするために他のデフォルトをセットします。

[out:csv(::id,::type,'name')][timeout:25]; (
  node["tourism"="museum"]({{bbox}});
  way["tourism"="museum"]({{bbox}});
  relation["tourism"="museum"]({{bbox}});
); out;

エクスポート / クエリ / OverpassQL (コンパクト) へ変換 リンクを使ってクエリーを{{bbox}}のようなextended shortcutsから正規のOverpass QLクエリーに変換するための単一文字列として取得するリンクを使用します。The 上記のクエリーlist of museumsを生成し、その出力をこのSPARQLクエリーを使って対応するウィキデータのエントリーの"クラス" (P31) を探します。

SELECT * WHERE {
  # 私たちはクエリーのオプティマイザーを"None" または "Runtime"にセットする必要があります。デフォルトの"Static"オプティマイザーは
  # ウィキデータで全ての位置を引き出した後にサービスからデータを取得しようとします。その結果、メモリ不足エラーを引き起こします。
  # 代わりに、まず最初にサービス(query = Noneと同じ順番で)または"Runtime"でのオンザフライの
  # パフォーマンス最適化を行うべきです。Blazegraphのヘルプを参照:
  # https://wiki.blazegraph.com/wiki/index.php/QueryOptimization#Join_Order_Optimization
  hint:Query hint:optimizer "None" .

  # Overpassで予め定義されたエリア内で博物館の一覧を取得する
  SERVICE wikibase:tabular {
    bd:serviceParam wikibase:otQuery '[out:csv(::id,::type,"name")][timeout:25];(node["tourism"="museum"](40.69,-74.09,40.76,-74.02);way["tourism"="museum"](40.69,-74.09,40.76,-74.02);relation["tourism"="museum"](40.69,-74.09,40.76,-74.02););out;' .
    ?type tabular:%40type 'string' .
    ?id tabular:%40id 'string' .  # Use string instead of integer to avoid another conversion in ?osmID creation below
    ?name tabular:name 'string' .
  }
  # Overpass の種別 & id フィールドから、動的にOSMオブジェクトのIDを生成する
  BIND(URI(CONCAT("https://www.openstreetmap.org/", ?type, "/", ?id)) as ?osmId)

  # Overpass の結果とRDFデータを合致させる
  # (OT からもwikidataと位置を参照できていました)
  ?osmId osmm:loc ?loc .

  # 存在する場合は、wikidataのIDとラベル付きのそのIDの種別(クラス)を取得
  OPTIONAL { 
    ?osmId osmt:wikidata ?wikidata .
    ?wikidata wdt:P31 ?instanceOf .
    SERVICE wikibase:label {
      bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en".
      ?instanceOf rdfs:label ?instanceOfLabel .
    }
  }
}

Run it (edit query)

パラメータ

入力パラメータ:

各パラメータは次の形式でなければなりません。bd:serviceParam wikibase:paramName <value>

名前 種別 説明
url string データソースへのURL。サービスにはurl または otQuery パラメータが必要です。
otQuery string CSV-formatted の結果をリターンするOverpass QLクエリー。クエリー全体が1行で書かれていなければなりません。アウトプット内では、特殊文字にはURLエンコードされたカラム名を使います(例: @id用にはtabular:%40id)。
format string パースに使うCSVFormat プロファイル。正規のURLにはDEFAULTを、Overpass クエリーにはTDFを使います
firstRowIsHeader boolean trueの場合、カラム名に最初の行を使います。デフォルトで、OTクエリーはこれをtrueにセットし、URLリクエストはデフォルトをフォーマットから使用します。
ignoreSurroundingSpaces boolean トリミングのふるまい。trueで前後のスペースを削除、falseでスペースをそのまま残します。doc参照。
commentMarker char 特定の文字にコメント開始マーカーをセットします。コメント開始文字は行の先頭でのみ認識されます。doc参照。
delimiter char 区切り文字をセットします。doc参照。
escape char エスケープ文字をセットします。doc参照。
quote char 引用符をセットします。doc参照。
useColumnNames boolean trueの場合は、tabular:columnNameを使用してカラムにアクセスします。そうでなければ、tabular:Nを使います。Nは0から始まるカラムの索引です。デフォルトでは、この値はfirstRowIsHeader と同じです。

出力パラメータ: 全ての出力パラメータは?variable tabular:columnName "dataType" または ?variable tabular:columnIndex "dataType"の形式内になければなりません。useColumnNames パラメータはこれがcolumnName または columnIndexであるかどうかコントロールしています。許可されたデータ種別: string, double, integer, uri。

ポリゴンファイルの生成

あなたのクエリーが?idフィールドを含み、その各値がユニークである場合は、ポリゴンを持つファイルの作成に使うことができ、そこには各ポリゴンのIDが ?id フィールドにセットされ、任意の追加フィールドがポリゴンのプロパティとして使えます。例えば、あなたのクエリーはアメリカの州の一覧を、各州の知事の名前を?governorフィールドとして付けて出力できるでしょう。結果は50の地物がそれぞれ"governor"プロパティを持つを持つファイルとなるでしょう。結果はMapshaperを使って表示されるでしょう。その結果を検査して簡素化したり、データファイルを追加したり、その他多くのジオメトリ操作を行えます。

このモードを使用するには、クエリーの先頭に#defaultView:MapRegions という行を追加してください。

このクエリーは英語とフランス語の名前、そのISO 3166-2コード、及びそのフラグ(ウィキメディア・コモンズ上のURL)を含む、すべてのカナダの州を表示します。

#defaultView:MapRegions
SELECT 
  ?id
  (SAMPLE(?label_en) as ?label_en)
  (SAMPLE(?label_fr) as ?label_fr)
  (SAMPLE(?iso_3166_2) as ?iso_3166_2)
  (SAMPLE(?flag) as ?flag)
WHERE {
  # List of regions, whose sub-regions we want
  VALUES ?entity { wd:Q16 } 

  SERVICE <https://query.wikidata.org/sparql> { 
    # P150 = "contains administrative territorial entity"
    # but must not have a P582 (end date) qualifier
    ?entity p:P150 ?statement .
    ?statement ps:P150 ?id .
    FILTER NOT EXISTS { ?statement pq:P582 ?x }

    # Get labels, ISO code, and flag image
    # for each sub-region, if available
    OPTIONAL { ?id rdfs:label ?label_en . FILTER(LANG(?label_en) = "en") }
    OPTIONAL { ?id rdfs:label ?label_fr . FILTER(LANG(?label_fr) = "fr") }
    OPTIONAL { ?id wdt:P300 ?iso_3166_2 }
    OPTIONAL { ?id wdt:P41 ?flag }
  }
}
# remove possible ID duplicates
GROUP BY ?id

Run it (edit query)

Quick-fix エディタ

Quick-fix エディタはコミュニティのフィードバックに基づき完全に再実装されました。Sophox参照

その他のクエリー

  • このクエリーサービスはコミュニティが維持しているquery example listを使っています - 「例」ボタン下のクエリーインターフェースから直接アクセス・検索できます。

現在の制限事項

  • ひとつ以上のタグがあるOSMノードだけを含みます。ウェイとリレーションはノードが空でも含まれています。
  • このデータベースはシンプルなタグのキー用の値だけを格納しています - 英文字、数字と記号 - : _. この基準を満たさないもの、例えばスペースやアクセント付きの文字、は値無しでosmm:badkey "bad tag key"として格納されています。
  • OSMのジオメトリはインポートされていませんが、たいていのオブジェクトにはosmm:loc (中心点)があり、ウェイにはosmm:isClosed (true/false)があります。

外部リンク