
Contents
実行環境 関連リンクと過去記事 PostgreSQL 用の汎用ウェブアクセス関数を、PL/Python で作成 作った関数のテスト(以上、1月4日) PL/Python で作ったウェブアクセス関数を、PL/v8 から使う(1月5日) WebAPI の例として、MediaWiki API を使ってみる PL/v8 で MediaWiki API の「タイトル → pageid」検索関数を作る(以上、1月7日) - 関数の改良(ⅰ)JSON
を処理して pageid を直接返す - 改良したものの、テーブルの複数行に対しては使いにくい
関数の改良(ⅱ)複数行に対するウェブアクセスを、ウィンドウ関数で 1 回にまとめる(1月9日、終)
関数の改良(ⅰ)JSON を処理して pageid を直接返す
昨日作ったselect plv8_MediaWiki_ex1('{東京,大阪,札幌}'); plv8_mediawiki_ex1 {"url":"https://en.wikipedia.org/w/api.php?action=query&format=json&titles=%E6%9D%B1% E4%BA%AC%7C%E5%A4%A7%E9%98%AA%7C%E6%9C%AD%E5%B9%8C","response":{"batchcomplete":"","q uery":{"pages":{"2126632":{"pageid":2126632,"ns":0,"title":"東京"},"3211539":{"pageid ":3211539,"ns":0,"title":"大阪"},"3211578":{"pageid":3211578,"ns":0,"title":"札幌"}}} }} (1 row)

そこでまず ↓ こんな風に改良
create or replace function plv8_MediaWiki_ex2(wiki_titles text[]) returns json language plv8 immutable as $$ var url = 'https://en.wikipedia.org/w/api.php?action=query&format=json&titles=' + encodeURIComponent(wiki_titles.join('|')), sql = "select convert_from(plpy_urlopen('" + url + "'), 'utf8')", res = plv8.execute(sql), objTmp = JSON.parse(res[0]['convert_from']); if (!objTmp) return null; var obj = objTmp['query']['pages'], pids = Object.keys(obj), resAry = []; // search a pageid matching each title for (var i = 0; i < wiki_titles.length; i++) { var titleTarget = wiki_titles[i]; for (var j = 0; j < pids.length; j++) { var pidCand = pids[j], objCand = obj[ pidCand ]; if (objCand['title'] === titleTarget) { var resObj = {}; resObj[titleTarget] = pidCand; resAry.push(resObj); break; } } }; return resAry; $$;
↓ 三つの検索語での使用例。検索語で完全一致する記事があれば当該
select plv8_MediaWiki_ex2('{東京,大阪,札幌}'); +------------------------------------------------------+ | plv8_mediawiki_ex2 | +------------------------------------------------------+ | [{"東京":2126632},{"大阪":3211539},{"札幌":3211578}] | +------------------------------------------------------+ (1 row)

記事が存在しない検索語は、pageid : -1
select plv8_MediaWiki_ex2('{東京,大阪,札幌幌}'); +---------------------------------------------------------+ | plv8_mediawiki_ex2 | +---------------------------------------------------------+ | [{"東京":"2126632"},{"大阪":"3211539"},{"札幌幌":"-1"}] | +---------------------------------------------------------+ (1 row)

ネットワーク非接続の場合など
select plv8_MediaWiki_ex2('{東京,大阪,札幌}'); NOTICE: URLError or HTTPError. failed to reach a server CONTEXT: PL/Python function "plpy_urlopen" SQL statement "select convert_from(plpy_urlopen('https://en.wikipedia.org/w/api.php?a ction=query&format=json&titles=%E6%9D%B1%E4%BA%AC%7C%E5%A4%A7%E9%98%AA%7C%E6%9C%AD%E5 %B9%8C'), 'utf8')" +--------------------+ | plv8_mediawiki_ex2 | +--------------------+ | | +--------------------+ (1 row)

改良したものの、テーブルの複数行に対しては使いにくい
実際には最初から検索語の配列があるというより、何らかのテーブルの列を検索語として考え、複数行に対し一括検索したい場面が多いのではないかと。そうなると前項で改良したストアドもまだまだ使いづらいです。例えばサンプルテーブルとして ↓ こんなデータで一括検索する場合。create table cities as select * from unnest('{東京,大阪,札幌幌,仙台,広島,北九州,福岡}' :: text[]) as city; select * from cities; +--------+ | city | +--------+ | 東京 | | 大阪 | | 札幌幌 | -- 検索結果なしのテスト用 | 仙台 | | 広島 | | 北九州 | | 福岡 | +--------+ (7 rows)
検索語の配列は
-- 見やすくするため、整形オフ&列を縦に並べて表示 \pset format unaligned \pset expanded on select ary, plv8_MediaWiki_ex2(ary) from ( select array_agg(city) as ary from cities ) foo; ary|{東京,大阪,札幌幌,仙台,広島,北九州,福岡} plv8_mediawiki_ex2|[{"東京":"2126632"},{"大阪":"3211539"},{"札幌幌":"-1"},{"仙台":"32 11582"},{"広島":"3211568"},{"北九州":"16326328"},{"福岡":"9336564"}]

一応やってみると ↓ こんな感じ。検索語は
-- 表示設定を元に戻した \pset format aligned \pset expanded off with a (ary1) as ( select array_agg(city) from cities ), b (ary2) as ( select plv8_MediaWiki_ex2(ary1) from a ), c (city, json) as ( select unnest(ary1), json_array_elements(ary2) from a, b ) select city, (json->>city) :: int as pageid from c; +--------+----------+ | city | pageid | +--------+----------+ | 東京 | 2126632 | | 大阪 | 3211539 | | 札幌幌 | -1 | | 仙台 | 3211582 | | 広島 | 3211568 | | 北九州 | 16326328 | | 福岡 | 9336564 | +--------+----------+ (7 rows)

せっかく
そこで次に、ウィンドウ関数を自作して「ウェブアクセスは