如何在扫描所有记录时禁用Google App Engine中的BadValueError(必填字段)值?

时间:2014-04-24 08:55:41

标签: google-app-engine google-cloud-datastore

我想扫描所有记录以检查数据中是否存在错误。

如何在缺少必填字段的情况下禁用BadValueError到没有中断扫描?

考虑到我不能将StringProperty更改为不需要,并且这些属性在实际代码中可能是十分之一 - 所以这样的解决方法没用?

class A(db.Model):
  x = db.StringProperty(required = True)

for instance in A.all():
  # check something
  if something(instance):
    instance.delete()

我是否可以使用某些功能直接读取datastore.Entity以避免此类问题而不需要验证?

4 个答案:

答案 0 :(得分:1)

我发现这个问题的解决方案是使用弹性查询,它忽略了查询引发的任何异常,你可以试试这个:

def resilient_query(query):
    query_iter = iter(query)
    while True:
            next_result = query_iter.next()
            #check something
            yield next_result
        except Exception, e:
            next_result.delete() 

query = resilient_query(A.query()) 

答案 1 :(得分:1)

如果使用ndb,则可以将所有模型作为ndb.Expando加载,然后修改值。这在db中似乎不可能,因为您无法为db中的查询指定一种与模型类不同的类型。

即使您的模型是在db中定义的,您仍然可以使用ndb来修复您的实体:

# Setup a new ndb connection with ndb.Expando as the default model.
conn = ndb.make_connection(default_model=ndb.Expando)
# Use this connection in our context.
ndb.set_context(ndb.make_context(conn=conn))

# Query for all A kinds
for a in ndb.Query(kind='A'):
  if a.x is None:
    a.x = 'A more appropriate value.'
    # Re-put the broken entity.
    a.put()

另请注意,此(以及列出的其他解决方案)将受限于您受限制的任何时间限制(即App Engine前端上的60秒)。如果您正在处理大量数据,那么您很可能希望编写自定义地图缩减作业来执行此操作。

答案 2 :(得分:0)

尝试将default属性选项设置为某些不存在的其他值。

class A(db.Model):
  x = db.StringProperty(required = True, default = <distinct value>)

然后加载属性并检查此值。

答案 3 :(得分:0)

你可以在你自己的Model子类中覆盖ndb.Model的_check_initialized(self)方法,并用你自己的逻辑替换默认逻辑(或者根据需要一起跳过)。