Logicaとは
LogicaとはGoogleが発表した論理プログラミング言語で、BigQueryやPostgreSQLのクエリにコンパイルして実行できます。
日本語ではこれらの記事で紹介されており、だいたいの概要は分かると思います。
引用すると次のような特徴があり、私の所属するチームではBigQueryでそれなりに複雑な処理が実装されているので、特に「モジュール機能があること」「テストが実施できる?(ドキュメントにも明確に記載がないのでまだ詳細不明)」ことに期待しています。また、GitHubのDiscussions(PageRank Alogrithm)を見る限り再帰も(回数は限定されてそうですが)使えるらしく、もしかするとBigQuery側で柔軟にアルゴリズムを実装していくことも可能かもしれません。
最初に、プログラミング言語Logicaの特徴を纏めておく。
- 論理型プログラミング言語: このカテゴリではPrologが有名
- SQLにコンパイルされる: 現状BigQueryとPostgreSQLに対応
- モジュール機構がある: SQLと比較した強み
- コンパイラはPythonで書かれている: Jupyter NotebookやGoogle Colabですぐ始められる
- Colabでチュートリアルが用意されているので、まずこちらからやると良いと思う。
ただ、チュートリアルやドキュメントを見る限りlogica
のコマンドで実行するか、Collabで実行するかという方法しか紹介されていません。そのため、私は「複雑なクエリをPythonのバッチ処理で実行したい」と考え、Python自体でlogicaをimportして実行してみました。
(※ただ、後から思いついたのですが、Python内で利用できなくても、Dockerのビルド時にlogicaをSQLに変換した結果を保存して利用すればいいだけかもしれません)
LogicaのプログラムをSQLに変換するPythonスクリプト
チュートリアルにあるこちらのLogicaプログラムをPython内で変換します。
@OrderBy(Mentions, "mentions desc");
@Limit(Mentions, 10);
Mentions(person:, mentions? += 1) distinct :-
gdelt-bq.gdeltv2.gkg(persons:, date:),
Substr(ToString(date), 0, 4) == "2020",
the_persons == Split(persons, ";"),
person in the_persons;
以下のようなスクリプトで実行できます。logica.pyの内容を追って、不要な処理を削除したものです。
from logica.parser_py import parse
from logica.compiler import universe
with open("./mentions.l") as f:
program = f.read()
# 構文木(?)に変換する
parsed_rules = parse.ParseFile(program)["rule"]
# SQLに変換する
program = universe.LogicaProgram(parsed_rules)
sql = program.FormattedPredicateSql("Mentions") # 呼び出したい変数(Mentions)を指定する
print(sql)
結果、以下のSQLが出力されます。このSQL文字列をBigQueryのクライアントで利用すればokです。
SELECT
x_3 AS person,
SUM(1) AS mentions
FROM
gdelt-bq.gdeltv2.gkg AS gdeltbq_gdeltv2_gkg, UNNEST(SPLIT(gdeltbq_gdeltv2_gkg.persons, ";")) as x_3
WHERE
(SUBSTR(CAST(gdeltbq_gdeltv2_gkg.date AS STRING), 0, 4) = "2020")
GROUP BY person ORDER BY mentions desc LIMIT 10;