1

我正在从现有架构自动创建 bulkloader.yaml,但由于repeated=True我的 KeyProperty 无法下载我的数据。

class User(ndb.Model):
    firstname = ndb.StringProperty()
    friends = ndb.KeyProperty(kind='User', repeated=True) 

自动创建的 bulkloader 如下所示:

- kind: User
  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: firstname
      external_name: firstname
      # Type: String Stats: 2 properties of this type in this kind.

    - property: friends
      external_name: friends
      # Type: Key Stats: 2 properties of this type in this kind.
      import_transform: transform.create_foreign_key('User')
      export_transform: transform.key_id_or_name_as_string

这是我收到的错误消息:

google.appengine.ext.bulkload.bulkloader_errors.ErrorOnTransform: Error on transform. Property: friends External Name: friends. Code: transform.key_id_or_name_as_string Details: 'list' object has no attribute 'to_path'

请问我能做什么?

可能的解决方案:

在托尼的提示之后,我想出了这个:

- property: friends
      external_name: friends
      # Type: Key Stats: 2 properties of this type in this kind.
      import_transform: myfriends.stringToValue(';') 
      export_transform: myfriends.valueToString(';')

我的朋友.py

def valueToString(delimiter):
    def key_list_to_string(value):
        keyStringList = []
        if value == '' or value is None or value == []:
            return None 
        for val in value:                
            keyStringList.append(transform.key_id_or_name_as_string(val))        
        return delimiter.join(keyStringList)
    return key_list_to_string

这行得通!编码虽然是 Unicode:UTF-8。确保在 LibreOffice 中打开文件,否则您会看到乱码。

最大的挑战是进口。这是我没有任何运气的想法:

def stringToValue(delimiter):    
    def string_to_key_list(value):
        keyvalueList = []
        if value == '' or value is None or value == []:
            return None        
        for val in value.split(';'):            
            keyvalueList.append(transform.create_foreign_key('User'))        
        return keyvalueList
    return string_to_key_list

我收到错误消息:

BadValueError: Unsupported type for property friends: <type 'function'>

根据数据存储查看器,我需要创建如下内容:

[datastore_types.Key.from_path(u'User', u'kave@gmail.com', _app=u's~myapp1')] 

更新 2:

托尼,您将成为 Bulkloader 的真正专家。谢谢你的帮助。你的解决方案奏效了!我已将其他问题移至新线程。

但是出现的一个关键问题是,当我创建新用户时,我可以看到我的friends字段显示为<missing>并且它工作正常。

现在,当我使用您的解决方案上传数据时,我会为那些没有任何朋友条目的用户看到一个<null>条目。不幸的是,这似乎打破了模型,因为朋友不能为空。

改变模型以反映这一点,似乎被忽略了。

friends = ndb.KeyProperty(kind='User', repeated=True, required=False)

请问我该如何解决这个问题?

更新:

进一步深入研究:当状态<missing>显示在数据查看器中时,它会在代码中显示friends = [] 但是当我通过 csv 上传数据时,我得到一个<null>,它转换为friends = [None]. 我知道这一点,因为我将数据导出到本地数据存储中,并且可以在代码中跟踪它。奇怪的是,如果我清空列表del user.friends[:],它会按预期工作。虽然通过 csv 上传时必须有更好的方法来设置它......

最终解决方案

事实证明,这是一个一年多以来一直没有解决的错误。

简而言之,即使 csv 中没有任何值,因为需要一个列表,gae 也会创建一个包含 None 的列表。这是游戏破坏性的,因为检索这样的模型最终会立即崩溃。

添加一个post_import_function,它会删除内部带有 None 的列表。

就我而言:

def post_import(input_dict, instance, bulkload_state_copy):
    if instance["friends"] is None:
        del instance["friends"]
    return instance

最后一切都按预期工作。

4

1 回答 1

1

当您使用重复属性并导出到 CSV 时,您应该进行一些格式化以将列表连接成 CSV 可以理解的格式。请在此处查看有关日期列表导入/导出的示例,希望对您有所帮助。

编辑:从较早的评论中添加导入转换的建议到这个答案

对于导入,请尝试以下操作:

 `from google.appengine.api import datastore 
    def stringToValue(delimiter): 
        def string_to_key_list(value): 
            keyvalueList = [] 
            if value == '' or value is None or value == []: return None 
            for val in value.split(';'): 
                keyvalueList.append(datastore.Key.from_path('User', val)) 
            return keyvalueList 
        return string_to_key_list`

如果你有 id 而不是 name ,添加像 val = int(val)

于 2013-07-05T11:16:25.970 回答