2011年2月9日水曜日

[Scala][sbt]DefaultWebProjectでwarではなくjarも作りたい

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
DefaultWebProjectだとsbt packageタスクでwarが作られますが、jarも作りたい時があった場合、こんな感じで。
lazy val jar = packageTask(packagePaths, jarPath, packageOptions).dependsOn(compile) describedAs "Creates a jar file."
sbt jarでjarファイルが作られます。

2011年2月7日月曜日

[GAE] bulkloaderをGAE/Jで使う

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
python版appengine-sdkを使ってcsvファイルからデータをDatastoreにロードすることができます。

準備

web.xmlにremote_api用のServletの設定を書く

<servlet>
  <servlet-name>remoteapi</servlet-name>
  <servlet-class>com.google.apphosting.utils.remoteapi.RemoteApiServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>remoteapi</servlet-name>
  <url-pattern>/remote_api</url-pattern>
</servlet-mapping>
security-constraintも追加しておいた方が良さげ。
<security-constraint>
  <web-resource-collection>
    <url-pattern>/remote_api</url-pattern>
  </web-resource-collection>
  <auth-constraint>
    <role-name>admin</role-name>
  </auth-constraint>
</security-constraint>

ロード設定用のyamlファイルを書く

python_preamble:
- import: base64
- import: re
- import: google.appengine.ext.bulkload.transform
- import: google.appengine.ext.bulkload.bulkloader_wizard
- import: google.appengine.api.datastore
- import: google.appengine.api.users

transformers:

- kind: Scores
  connector: csv

  connector_options:
    encoding: ms932

  property_map:
    - property: __key__
      external_name: id
      import_transform: int

    - property: name
      external_name: name

    - property: score
      external_name: score
      import_transform: transform.none_if_empty(float)
  • キーにidではなく文字列(name)を使用する場合は、import_transform: intは不要。
  • import_transformに他に指定できる例
    日付: transform.import_date_time('%Y/%m/%d %H:%M')
    固定値: import_transform: lambda x:1
    数値変換: import_transform: lambda x:int(x)*100
    ※lambdaは引数の:の後にスペースを空けるとダメな様です

    ロード用CSV
    id,name,score
    1,Alice,5.0
    2,Bob,2.5
    3,Caroline,
    

    ロード用コマンド

    appcfg.py upload_data --filename=test.csv --config_file=test.yml --url=http://{appid}.appspot.com/remote_api --application={appid} --kind=Scores -v
    
    ※{appid}はアプリケーションIDに置き換える

    security-constraintの設定をしている場合、毎回管理者アドレス/パスワードの入力が必要です。
    ローカルのdev_appserverだとエラーが出て動きませんでした…

    こんな感じに反映されます。
    ※1万件だと約500秒(8分ちょっと)くらいかかりました(CPU Timeを無料Quotaの10%ほど消費します)

    その他注意点

  • slim3を使っている場合、filterの設定があると、"ProtocolBufferDecodeError: corrupted"の様なエラーが出てしまうので一時的にコメントアウトして回避しました。(※他にいい方法があれば教えて下さい…

    2/11追記: bulkload用にfilterをコメントアウトしたversionをデプロイしておいて、--url=http://latest.bulkload.{appid}.appspot.com/remote_api みたいに指定するといいかも

    3/22追記:slim3ではなくscenic3の方の設定でした。matcherで/remote_apiを除外したらOK。

    参考: Ikai Lan says / Using the bulkloader with Java App Engine
  •