使用游标分页时更新 ndb 中的实体
Updating entities in ndb while paging with cursors
简而言之,我必须在“第二人生”中制作一个脚本,与 AppEngine 应用程序通信,更新 ndb 数据库中的记录。从数据库中提取的记录作为批处理(一页)发送到 LSL 脚本,该脚本更新客户,然后要求 Web 应用程序将这些客户标记为已在数据库中更新。
为了创建批次,我在(整数)属性 update_ver==0
上使用了查询,并使用 fetch_page()
为下一批次生成游标。此游标也作为 urlsafe()
编码参数发送到 LSL 脚本。
为了将客户标记为已更新,将 update_ver
设置为其他值,例如 2,并通过 put_async()
更新实体。由于之前发送的光标,LSL 脚本获取下一批。
我的问题很简单:在网络应用程序中,由于查询属性 update_ver
不再满足过滤器,我的光标是否仍然有效?还是我必须使用其他策略?
去除不相关的部分(包括身份验证),我的代码目前看起来像这样(客户是我数据库中的实体)。
class GetCustomers(webapp2.RequestHandler): # handler that sends batches to the update script in SL
def get(self):
cursor=self.request.get("next",default_value=None)
query=Customer.query(Customer.update_ver==0,ancestor=customerset_key(),projection=[Customer.customer_name,Customer.customer_key]).order(Customer._key)
if cursor:
results,cursor,more=query.fetch_page(batchsize,start_cursor=ndb.Cursor(urlsafe=cursor))
else:
results,cursor,more=query.fetch_page(batchsize)
if more:
self.response.write("more=1\n")
self.response.write("next={}\n".format(cursor.urlsafe()))
else:
self.response.write("more=0\n")
self.response.write("n={}\n".format(len(results)))
for c in results:
self.response.write("c={},{},{}\n".format(c.customer_key,c.customer_name,c.key.urlsafe()))
self.response.set_status(200)
更新数据库中客户实体的处理程序如下。 c= 参数是要更新的记录的 urlsafe()
编码实体键,nv=
参数是其 update_ver
属性的新版本号。
class UpdateCustomer(webapp2.RequestHandler):
@ndb.toplevel # don't exit until all async operations are finished
def post(self):
updatever=self.request.get("nv")
customers=self.request.get_all("c")
for ckey in customers:
cust=ndb.Key(urlsafe=ckey).get()
cust.update_ver=nv # filter in the query used to produce the cursor was using this property!
cust.update_date=datetime.datetime.utcnow()
cust.put_async()
else:
self.response.set_status(403)
这会按预期工作吗?感谢您的帮助!
您的策略会奏效,这就是使用这些游标的全部意义所在,因为它们非常高效,您可以按预期获得下一批,而不管前一批发生了什么。
附带说明一下,您还可以优化 UpdateCustomer
,而不是 retrieving/saving 一个接一个,您可以在 batches using for example the ndb.put_multi_async
.
中做一些事情
简而言之,我必须在“第二人生”中制作一个脚本,与 AppEngine 应用程序通信,更新 ndb 数据库中的记录。从数据库中提取的记录作为批处理(一页)发送到 LSL 脚本,该脚本更新客户,然后要求 Web 应用程序将这些客户标记为已在数据库中更新。
为了创建批次,我在(整数)属性 update_ver==0
上使用了查询,并使用 fetch_page()
为下一批次生成游标。此游标也作为 urlsafe()
编码参数发送到 LSL 脚本。
为了将客户标记为已更新,将 update_ver
设置为其他值,例如 2,并通过 put_async()
更新实体。由于之前发送的光标,LSL 脚本获取下一批。
我的问题很简单:在网络应用程序中,由于查询属性 update_ver
不再满足过滤器,我的光标是否仍然有效?还是我必须使用其他策略?
去除不相关的部分(包括身份验证),我的代码目前看起来像这样(客户是我数据库中的实体)。
class GetCustomers(webapp2.RequestHandler): # handler that sends batches to the update script in SL
def get(self):
cursor=self.request.get("next",default_value=None)
query=Customer.query(Customer.update_ver==0,ancestor=customerset_key(),projection=[Customer.customer_name,Customer.customer_key]).order(Customer._key)
if cursor:
results,cursor,more=query.fetch_page(batchsize,start_cursor=ndb.Cursor(urlsafe=cursor))
else:
results,cursor,more=query.fetch_page(batchsize)
if more:
self.response.write("more=1\n")
self.response.write("next={}\n".format(cursor.urlsafe()))
else:
self.response.write("more=0\n")
self.response.write("n={}\n".format(len(results)))
for c in results:
self.response.write("c={},{},{}\n".format(c.customer_key,c.customer_name,c.key.urlsafe()))
self.response.set_status(200)
更新数据库中客户实体的处理程序如下。 c= 参数是要更新的记录的 urlsafe()
编码实体键,nv=
参数是其 update_ver
属性的新版本号。
class UpdateCustomer(webapp2.RequestHandler):
@ndb.toplevel # don't exit until all async operations are finished
def post(self):
updatever=self.request.get("nv")
customers=self.request.get_all("c")
for ckey in customers:
cust=ndb.Key(urlsafe=ckey).get()
cust.update_ver=nv # filter in the query used to produce the cursor was using this property!
cust.update_date=datetime.datetime.utcnow()
cust.put_async()
else:
self.response.set_status(403)
这会按预期工作吗?感谢您的帮助!
您的策略会奏效,这就是使用这些游标的全部意义所在,因为它们非常高效,您可以按预期获得下一批,而不管前一批发生了什么。
附带说明一下,您还可以优化 UpdateCustomer
,而不是 retrieving/saving 一个接一个,您可以在 batches using for example the ndb.put_multi_async
.