ドハマりしたのでメモ
GAEなサービスでDatastoreに合ったデータをバックアップした後、BigQueryに投入するとBigQuery上からSQLっぽいもので検索が出来るので便利です。
ですが、RDBとは仕組みなどが違うため、探したレコードを表示する時におもわぬところでハマりますorz
やったこと
とあるGAEのDatastoreをバックアップ後、BigQueryに取り込んで以下のようなGQLを書いてみました
SELECT __key__.name,functions,codes,airports,level,codes
FROM [appengine.data]
where (codes is null) and (airports is null) LIMIT 1000
こんなエラーが出ますorz
Cannot query the cross product of repeated fields airports and codes.
上記のModelはSlim3でいうと以下のような感じです。
@Attribute(primaryKey = true)
private Key key;
@Attribute(unindexed = true)
private List<String> airports = new ArrayList<>();
@Attribute(unindexed = true)
private List<String> codes = new ArrayList<>();
//以下省略
上記のようなModelの定義だとBigQuery上はList定義したプロパティーがREPEATEDになりRDBでいうと1対Nの関連付けがなされた感じになります。
このため、複数のREPEATEDの要素を含むレコードを検索、表示しようとすると
そこ複数件レコードがあるからな!
と言うエラーになります。
解決方法としては、 FLATTEN関数を使って1カラムにならせば良いのですが、これFROM句で1カラムに対してだけ設定可能な関数のようなので、複数REPEATEDがあると以下のようなことになりますorz
SELECT __key__.name,functions,codes,airports,level,books
FROM
FLATTEN(
(select __key__.name,functions,codes,airports,level,codes FROM
FLATTEN(
(SELECT __key__.name,functions,codes,airports,domInt,codes
FROM flatten([appengine.usernotificationsetting],codes )
where (codes is null)
), functions)
where (codes is null)
), categories)
where (level is null) LIMIT 1000
それと、where句の最後にLIMITを付けておいたほうが安心です。
数万レコードあるテーブルに対してうっかり全文表示するようなQueryを投げるとBigQueryと言っても3分以上ぐるぐるしてて結果が返ってこなかったりします(;´Д`)