更改导航台字段的属性类型时迁移数据 [英] Migrating data when changing an NDB field's property type

查看:24
本文介绍了更改导航台字段的属性类型时迁移数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我最初创建了一个 ndb.Model 并且想要更改一个字段的 ndb 属性类型(例如 IntegerProperty 到 StringProperty),但想要转换存储在该字段中的当前数据,这样我就不会丢失该数据.一种方法是简单地创建一个新的字段名称,然后使用脚本迁移数据,但还有其他更方便的方法来完成此操作吗?

Suppose I initially create an ndb.Model and wanted to change a field's ndb property type (e.g. IntegerProperty to StringProperty), but wanted to cast the current data stored in that field so that I don't lose that data. One method would be to simply create a new field name and then migrate the data over with a script, but are there other more convenient ways of accomplishing this?

例如,假设我有以下模型:

For example, suppose I had the following model:

class Car(ndb.Model):
    name = ndb.StringProperty()
    production_year = ndb.IntegerProperty()

我存储了实体的一个实例:

And I stored an instance of the entity:

c = new Car()
c.name = "Porsche"
c.production_year = 2013 

并且想将 production_year 更改为 ndb.StringProperty() 而不会丢失"我设置的值(它仍然存在,但无法检索).如果我只是将 production_year 更改为 ndb.StringProperty() 的实例,则字段值不会报告有意义的值,因为类型不匹配.

And wanted to change production_year to an ndb.StringProperty() without "losing" the value I set (it would still exist, but would not be retrievable). If I just change production_year to an instance of ndb.StringProperty(), the field value does not report a value which makes sense since the type doesn't match.

因此,如果我将模型更改为:

So if I changed the model to:

class Car(ndb.Model):
    name = ndb.StringProperty()
    production_year = ndb.StringProperty()

尝试使用点符号检索字段将导致值为 None.任何人遇到这种情况,你能解释一下你做了什么来解决它吗?谢谢.

Attempting to retrieve the field with dot notation would result in a value of None. Anyone run into this situation, and could you explain what you did to solve it? Thanks.

推荐答案

你如何处理这将取决于你有多少实体.如果您的实体数量相对较少,例如在 10000 中,我将只使用 remote_api 并从数据存储中检索原始底层数据并直接操作数据,然后将其写回,而不是使用模型.例如,这将获取原始实体,并且可以像字典一样访问属性.这段代码几乎是从较低级别的 appengine SDK 代码中提取的.

How you approach this will depend on how many entities you have. If you a relatively small number of entities say in the 10000's I would just use the remote_api and retrieve the raw underlying data from the datastore and manipulate the data directly then write it back, not using the models. For instance this will fetch raw entities as and properties can be accessed like a dictionary. This code is pretty much lifted from the lower level appengine SDK code .

from google.appengine.api import datastore
from google.appengine.api import datastore_errors

def get_entities(keys):
    rpc = datastore.GetRpcFromKwargs({})
    keys, multiple = datastore.NormalizeAndTypeCheckKeys(keys)
    entities = None
    try:
        entities = datastore.Get(keys, rpc=rpc)
    except datastore_errors.EntityNotFoundError:
        assert not multiple

    return entities

def put_entities(entities):
    rpc = datastore.GetRpcFromKwargs({})
    keys = datastore.Put(entities, rpc=rpc)
    return keys

你可以按如下方式使用它(我使用 fetch 来简化这个例子的代码明智)

You would use this as follows (I am using fetch to simplify things a bit code wise for this example)

x = Car.query(keys_only=True).fetch(100)
results = get_entities([i.to_old_key() for i in x])

for i in results:
    i['production_year'] = unicode(i['production_year'])

put_entities(results)

这是我拥有的旧代码,datastore.NormalizeAndTypeCheckKeys 采用旧的 db 样式键,我没有看到 ndb 样式键是否有等效功能,但这确实有效.(刚刚测试过;-)

This is old code I have and datastore.NormalizeAndTypeCheckKeys takes the old db style key, I haven't looked to see of there is an equivalent function for ndb style keys, but this does work. (Just tested it ;-)

这种方法允许您在不部署任何新代码的情况下迁移数据.
如果您有数百万个实体,那么您应该查看其他处理方法,即使用此代码和使用 mapreduce.

This approach allows you to migrate data without deploying any new code.
If you have millions of entities then you should look at other approaches for processing, ie using this code and using mapreduce.

这篇关于更改导航台字段的属性类型时迁移数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆