1

我认为我的问题类似于:BulkLoader -export_transformhttps://stackoverflow.com/questions/3220911/gae-datastore-export-transform

基本上,我使用bulkloader 来备份和恢复我创建的实体。为了测试,我使用了“游戏”类型并将其输出到名为 game.csv 的 csv 文件中。

这是我经历的过程:

  1. 使用以下命令将游戏类型下载到 game.csv:

    appcfg.py download_data --config_file=bulkloader.yaml --kind=Game --filename=game.csv --application=MyAppId --url= http://MyAppId.appspot.com/remote_api --rps_limit=500 --带宽限制=2500000 --batch_size=100

  2. 删除所有游戏实体。然后我检查了我的应用程序的管理门户数据存储查看器选项卡,我发现我的数据存储中没有更多实体。

  3. 使用使用创建的 game.csv 上传游戏类型(命令与download_data相同,但使用upload_data):

    appcfg.py upload_data --config_file=bulkloader.yaml --kind=Game --filename=game.csv --application=MyAppId --url= http://MyAppId.appspot.com/remote_api --rps_limit=500 --带宽限制=2500000 --batch_size=100

  4. 运行一个通过“名称”检索实体的 servlet(这是下面 Game.java 中显示的属性)。

出现以下错误:

Uncaught exception from servlet
java.lang.IllegalStateException: Loaded Entity has name but com.example.app.model.Game has no String @Id
    at com.googlecode.objectify.impl.ConcreteEntityMetadata.setKey(ConcreteEntityMetadata.java:343)
    at com.googlecode.objectify.impl.ConcreteEntityMetadata.toObject(ConcreteEntityMetadata.java:210)
    at com.googlecode.objectify.impl.QueryImpl$ToObjectIterator.translate(QueryImpl.java:640)
    at com.googlecode.objectify.impl.QueryImpl$ToObjectIterator.translate(QueryImpl.java:629)
    at com.googlecode.objectify.util.TranslatingIterator.next(TranslatingIterator.java:35)
    at com.googlecode.objectify.impl.QueryImpl.list(QueryImpl.java:470)

我怀疑这与我的bulkloader.yaml文件没有为__key__属性配置正确有关。所以我把它贴在下面:

- 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:

- kind: Game
  connector: csv
  connector_options:
    # TODO: Add connector options here--these are specific to each connector.
  property_map:
    - property: __key__
      external_name: key
      export_transform: transform.key_id_or_name_as_string

    - property: __scatter__
      #external_name: __scatter__
      # Type: ShortBlob Stats: 56 properties of this type in this kind.

    - property: genre
      external_name: genre
      # Type: String Stats: 6639 properties of this type in this kind.

    - property: name
      external_name: name
      # Type: String Stats: 6639 properties of this type in this kind.

    - property: releasedate
      external_name: releasedate
      # Type: Date/Time Stats: 6548 properties of this type in this kind.
      import_transform: transform.import_date_time('%Y-%m-%dT%H:%M:%S')
      export_transform: transform.export_date_time('%Y-%m-%dT%H:%M:%S')

在删除和上传数据之前,“游戏”类型(在应用程序管理门户的数据存储查看器选项卡中)显示ID/NAME带有超链接的列,看起来像ID=12345ID=67890 ... 对于每个实体行。

上传后,datastre 查看器会显示带有超链接的ID/NAME列,这些超链接看起来像NAME=12345NAME=67890 ... 对于每个实体行。


可能的原因?

我实际上已经在https://groups.google.com/forum/?hl=en#!topic/objectify-appengine/FFuB2Onfnzc上发布了我的问题,但我们不知道避免在何时将__key__属性转换为字符串的语法上传回数据。

Jeff(Objectify3.0 的创建者)说:

错误消息表明数据存储区中的数据为字符串名称键,但您的游戏实体具有数字长 @Id。我真的不知道批量加载程序的语法,但最可疑的行是这一行:

export_transform: transform.key_id_or_name_as_string

看起来您在这里将所有数字 id 转换为字符串,这将是您的问题。将它们保留为数字。

我试过删除,export_transform: transform.key_id_or_name_as_string但是当我下载时,csv文件是空的。

也许一个解决方案是避免使用--config_file参数和bulkloader.yaml文件,只让 bulkloader 下载/上传数据而不进行任何转换?


额外信息,以防可能相关

我正在使用 objectify3.0.jar 来操作我的 GAE 数据存储。所以我的游戏类型看起来像这样:

public class Game {
    @Id private Long id; //This is my key property, auto generated by objectify  
    private String name;
    private String genre; 
    private Date releasedate;

    //ommitting getters and setters 
}
4

2 回答 2

1

我做了一些实验,我相信我有解决方案。

我实际上是从我问的另一篇 stackoverflow 帖子中得到这个想法的:Using Java Google App Engine bulkloader to download entire datastore to one csv file

解决方法是避免使用--config_fileand bulkloader.yaml

我使用以下内容将各种下载到单个 csv 文件:

appcfg.py download_data --filename=backup.csv --application=MyAppId --url=http://MyAppId.appspot.com/remote_api --rps_limit=500 --bandwidth_limit=2500000 --batch_size=100

我使用以下内容将单个 csv 文件上传回数据存储区:

appcfg.py upload_data --filename=backup.csv --application=MyAppId --url=http://MyAppId.appspot.com/remote_api --rps_limit=500 --bandwidth_limit=2500000 --batch_size=100

它们是相同的命令,但只是download_data互换upload_data了。

这个想法只是让 appcfg 下载和上传所有实体(不是具体的),即不使用任何导出或导入转换。

于 2011-05-16T23:55:49.607 回答
0

为避免在导入时将密钥中的 Id (Integer) 转换为 Name,请查看以下帖子:

Bulkloader:如何将 transform.create_foreign_key() 定义为 int?

于 2014-01-05T17:35:43.453 回答