Custom properties not saved correctly for Expando models in repeated StructuredProperty

丶灬走出姿态 提交于 2019-12-04 19:00:46

This is a fundamental problem with how ndb stores the StructuredProperty. Datastore does not currently have a way to store this, so ndb basically explodes your properties.

For example, consider the entity:

HUser(email='test@example.com'.
      accounts=(Account(type='fb',
                        account_id='1',
                        state='1',
                        access_token='1'),
                Account(type='tw',
                        account_id='2',
                        state='2',
                        access_token='2',
                        access_token_secret='2')))

This will actually get stored in an entity that looks like:

{
 email : 'test@example.com',
 accounts.type : ['fb', 'tw'],
 accounts.account_id : ['1', '2'],
 accounts.state : ['1', '2'],
 accounts.access_token : ['1', '2'],
 accounts.access_token_secret : ['2']
}

Because you are using an ndb.Expando, ndb doesn't know that it should populate the access_token_secret field with a None for the facebook account. When ndb repopulates your entities, it will fill in the access_token_secret for the first account it sees, which is the facebook account.

Restructuring your data sounds like the right way to go about this, but you may want to make your HUser an ancestor of the Account for that HUser so that you query for a user's accounts using strong consistency.

From what I understand, it seems like App Engine NDB does not support Expando entities containing Expando entities themselves.

One thing that I didn't realize at first is that my HUser model inherits from Google's User class, which is precisely an Expando model!

So without even knowing it, I was trying to put a repeated StructuredProperty of Expando objects inside another Expando, which seemingly is not supported (I didn't find anything clearly written on this limitation, however).

The solution is to design the data model in a different way. I put my Account objects in a separate entity kind (and this time, they are truly Expando objects!), and I've added a KeyProperty to reference the HUser entity. This involves more read/write ops, but the code is actually much simpler to read now...

I'll mark my own question as answered, unless someone has another interesting input regarding the limitation found here.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!