使用游标分页时更新 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.

中做一些事情