使用java google app engine bulkloader.yaml在__key__上使用export_transform上传数据将ID / NAME coloumn从id(long)更改为name(string)

时间:2011-05-16 00:47:38

标签: java google-app-engine bulkloader

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

基本上,我正在使用bulkloader来备份和恢复我创建的实体。 测试我正在使用“Game”类型并将其输出到名为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 --bandwidth_limit = 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 --bandwidth_limit = 2500000 --batch_size = 100

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

  5. 发生以下错误:

    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')
    

    在删除和上传数据之前,“Game”类型(在应用管理门户的数据存储区查看器标签中)显示ID/NAME列,其超链接看起来像<对于每个有权行,strong> ID = 12345 , ID = 67890 ....

    上传后,datastire查看器会显示ID/NAME列,其中的超链接看起来像 NAME = 12345 NAME = 67890 ...对于每个有权行


    可能的原因?

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

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

    错误消息表明数据存储区中的数据为String名称 key,但你的Game实体有一个数字Long @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 文件,只是让批量加载程序下载/上传数据而不进行任何转换?


    可能相关的额外信息

    我正在使用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 
    }
    

2 个答案:

答案 0 :(得分:1)

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

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

修复方法是避免使用--config_filebulkloader.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_dataupload_data

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

答案 1 :(得分:0)

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

Bulkloader: How to define the transform.create_foreign_key() as int?