1

既存のスキーマから自動的に bulkloader.yaml を作成していますrepeated=Trueが、KeyProperty が原因でデータのダウンロードに問題があります。

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

自動作成されたバルクローダーは次のようになります。

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

myfriends.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 ビューアーによると、次のようなものを作成する必要があります。

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

更新 2:

トニー、あなたは Bulkloader の真の専門家です。ご協力いただきありがとうございます。あなたのソリューションはうまくいきました!別の質問を新しいスレッドに移動しました。

しかし、表示される重大な問題の 1 つは、新しいユーザーを作成すると、自分のfriendsフィールドが次のように表示され<missing>、正常に機能することです。

ソリューションを使用してデータをアップロードすると、友人のエントリがないユーザーのエントリが表示されます<null>。残念ながら、友人を null にすることはできないため、これはモデルを壊しているようです。

これを反映するようにモデルを変更すると、無視されるようです。

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

どうすればこれを修正できますか?

アップデート:

さらに掘り下げます:<missing>データ ビューアーにステータスが表示されると、コードで表示されますが、friends = [] csv 経由でデータをアップロードすると<null>、 に変換されfriends = [None]ます。データをローカル データ ストレージにエクスポートし、それをコードで追跡できたので、私はこれを知っています。奇妙なことに、リストを空にすると、del user.friends[:]期待どおりに機能します。ただし、csv経由でアップロードするときに設定するより良い方法があるはずです...

最終的解決

これは、1 年以上解決されていないバグであることが判明しました。

要するに、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