いまどきのGAE/Py bulkloader

GAE/Pyでbulkloaderを使ってデータをアップロードする - すぎゃーんメモのあたりからGAE/Pyをほとんど触ってなくて最近の事情も知らなかったのだけど、最近久々に触ってみたらこのへんもちょっと変わっているようで。
Backing Up and Restoring  |  Python  |  Google Cloud Platform
以前はbulkloader.Loaderを継承したクラスの.pyを作ってそれを使う、というやり方しかなかったと記憶しているのだけど、今はそのへんの変換方法をyamlで指定することで代替可能になっているようで。

#!/usr/bin/env python
from google.appengine.ext import db

class Tweet(db.Model):
    date_time = db.DateTimeProperty(required=True)
    tweet     = db.StringProperty(required=True)

とかいうModelクラスを作った場合、
まずapp.yaml

builtins:
- remote_api: on

という2行を追加する。これも以前はhandlerで指定していたはずだけど、デフォルト設定で問題ないなら(受けるURLを変更したい場合はhandlerに明記するっぽい)上記の2行だけで良いらしい。

appcfg.py create_bulkloader_config --filename=bulkloader.yaml .

といったコマンドでyamlのひな形を生成してもらえる。ローカルでアプリを立ち上げているなら

appcfg.py create_bulkloader_config --url=http://localhost:8080/_ah/remote_api --filename=bulkloader.yaml .

とかでいいのかな。すると以下のようなbulkloader.yamlが作られる。

# Autogenerated bulkloader.yaml file.
# You must edit this file before using it. TODO: Remove this line when done.
# At a minimum address the items marked with TODO:
#  * Fill in connector and connector_options
#  * Review the property_map.
#    - Ensure the 'external_name' matches the name of your CSV column,
#      XML tag, etc.
#    - Check that __key__ property is what you want. Its value will become
#      the key name on import, and on export the value will be the Key
#      object.  If you would like automatic key generation on import and
#      omitting the key on export, you can remove the entire __key__
#      property from the property map.

# If you have module(s) with your model classes, add them here. Also
# change the kind properties to model_class.
python_preamble:
- import: base64
- import: re
- import: google.appengine.ext.bulkload.transform
- import: google.appengine.ext.bulkload.bulkloader_wizard
- import: google.appengine.ext.db
- import: google.appengine.api.datastore
- import: google.appengine.api.users

transformers:

このtransformersに、以下のように追記する

transformers:
- kind: Tweet
  connector: csv
  property_map:
    - property: date_time
      external_name: date_time
      import_transform: transform.import_date_time('%Y-%m-%d %H:%M:%S')
    - property: tweet
      external_name: tweet

こうするとによりcsvファイルからインポートする際に文字列データをどう変換してdatastoreに格納するかを指定できるようだ。

date_time,tweet
2010-10-24 18:00:00,ほげほげほげ
2010-10-24 18:05:00,ふがふがふが

といったdata.csvを用意して、

appcfg.py upload_data --config_file=bulkloader.yaml --filename=data.csv --kind=Tweet .

とやると、csvのデータがアップロードされる。date_timeはちゃんとdatetime型に、tweetはもともと文字列なのでそのまんま。
実際どんな変換方法を指定できるのかはgoogle.appengine.ext.bulkload.transformを読むしかない…のかな。keyを指定して他のエンティティと繋げたりとか色々やろうとすればできそうなかんじだった。