我正在从现有架构自动创建 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
最后一切都按预期工作。