Google app engine appengine:从DB转换到NDB,并且在查询对象中存在迭代问题

Google app engine appengine:从DB转换到NDB,并且在查询对象中存在迭代问题,google-app-engine,google-cloud-datastore,app-engine-ndb,Google App Engine,Google Cloud Datastore,App Engine Ndb,我试图遍历一个查询,我的代码是为DB设置的。现在我正在使用NDB,我对语法感到困惑。基本上,在这段代码中,我试图为搜索API构建一个索引。我的数据库很大(约30000个实体),每个实体都将成为一个文档。我认为最好的方法是使用任务队列来分割作业 无论如何,代码如下: q = Database.query() q.filter(Database.title > None) numEntities = q.count(limit=50000) logging.in

我试图遍历一个查询,我的代码是为DB设置的。现在我正在使用NDB,我对语法感到困惑。基本上,在这段代码中,我试图为搜索API构建一个索引。我的数据库很大(约30000个实体),每个实体都将成为一个文档。我认为最好的方法是使用任务队列来分割作业

无论如何,代码如下:

    q = Database.query()
    q.filter(Database.title > None)
    numEntities = q.count(limit=50000)
    logging.info(num)
    counter = 0 
    batchsize = 999

    while (counter<numEntities):
        logging.info(counter)
        if (counter == 0):
            resultsFetched = 0
            for p in q:
                resultsFetched+=1
                counter += 1
                if p.identifier:
                    # add code to call worker here
                    taskqueue.add(queue_name='buildSearchIndexWorker',target='buildsearch',url='/tasks/buildSearchIndexWorker',params={'ID':p.identifier})

                    if (resultsFetched == batchsize):
                        a, startCursor, more = q.fetch_page(999)
                        break
        else: 
            q.fetch_page(999,start_cursor = startCursor)
            resultsFetched = 0
            for p in q:
                resultsFetched+=1
                counter += 1
                if p.identifier:
                    # add code to call worker here
                    taskqueue.add(queue_name='buildSearchIndexWorker',target='buildsearch',url='/tasks/buildSearchIndexWorker',params={'ID':p.identifier})

                    if (resultsFetched == batchsize):
                        a, startCursor, more = q.fetch_page(999)
                        break
q=Database.query()
q、 过滤器(Database.title>None)
数量=数量计数(限制=50000)
logging.info(num)
计数器=0
batchsize=999

而(counter关于您现有代码的一些评论:

最好避免运行
q.count()
。当尝试对大型查询进行迭代时,无法确定您是否能够在任务超时之前完成整个迭代。其次,我上次检查的
q.count()
,数量限制为1000个实体

我解决这个问题的简单方法是(主要考虑这个psuedo代码):

def\u迭代和索引(游标=无):
query=MyModel.query(key_only=True)#每次都需要重新构造查询
结果,光标,更多=查询。获取页面(批量大小或999,开始光标=光标)
#立即启动此任务以继续此查询。
如果更多:
deferred.deferred(_iterate_和_index,游标)
queue=taskqueue.queue('buildSearchIndexWorker')
任务\u至\u添加=[]
对于实体_输入结果:
task=taskqueue.task(target='buildsearch',
url='/tasks/buildSearchIndexWorker',
params={'entity_key':entity_key.urlsafe()})
任务\u到\u添加.附加(任务)
#将任务添加到队列,每次100个(100是API限制)
当任务添加到任务时:
添加(任务添加到任务添加[:100])
tasks_to_add=tasks_to_add[100:]
需要注意的一些事项:

  • 如果在添加所有任务之前终止运行时,任务将再次运行。如果单个实体不被索引两次很重要,请使用TaskName创建幂等性
  • 为了减少API调用,我将100个任务分批添加到队列中。100是一个API限制
  • 我没有将
    .identifier
    传递给任务,而是选择让查询只使用
    来提高查询效率,因为在实际查询过程中,您不需要任何有关实体的数据。这将节省您的时间和金钱
  • 使用
    fetch\u页面的
    more
    将不再需要使用
    q.count()
  • I
    deferred。在实际处理批处理之前,推迟下一次迭代。这可以保持并行运行并加快整个操作。它还可以防止光标过时
了解更多有关


我建议您看看这个库,它使用延迟任务(又称taskqueue)来解决大批量迭代,并允许您使用易于实现的模式来解决类似的问题。

关于您现有代码的一些评论:

最好避免运行
q.count()
。当尝试对大型查询进行迭代时,无法确定您是否能够在任务超时之前完成整个迭代。其次,我上次检查的
q.count()
,数量限制为1000个实体

我解决这个问题的简单方法是(主要考虑这个psuedo代码):

def\u迭代和索引(游标=无):
query=MyModel.query(key_only=True)#每次都需要重新构造查询
结果,光标,更多=查询。获取页面(批量大小或999,开始光标=光标)
#立即启动此任务以继续此查询。
如果更多:
deferred.deferred(_iterate_和_index,游标)
queue=taskqueue.queue('buildSearchIndexWorker')
任务\u至\u添加=[]
对于实体_输入结果:
task=taskqueue.task(target='buildsearch',
url='/tasks/buildSearchIndexWorker',
params={'entity_key':entity_key.urlsafe()})
任务\u到\u添加.附加(任务)
#将任务添加到队列,每次100个(100是API限制)
当任务添加到任务时:
添加(任务添加到任务添加[:100])
tasks_to_add=tasks_to_add[100:]
需要注意的一些事项:

  • 如果在添加所有任务之前终止运行时,任务将再次运行。如果单个实体不被索引两次很重要,请使用TaskName创建幂等性
  • 为了减少API调用,我将100个任务分批添加到队列中。100是一个API限制
  • 我没有将
    .identifier
    传递给任务,而是选择让查询只使用
    来提高查询效率,因为在实际查询过程中,您不需要任何有关实体的数据。这将节省您的时间和金钱
  • 使用
    fetch\u页面的
    more
    将不再需要使用
    q.count()
  • I
    deferred。在实际处理批处理之前,推迟下一次迭代。这可以保持并行运行并加快整个操作。它还可以防止光标过时
了解更多有关


我建议您看看这个库,它使用延迟任务(又称taskqueue)来解决大批量迭代,并允许您使用易于实现的模式来解决类似的问题。

关于您现有代码的一些评论:

最好避免运行
q.count()
。当尝试对大型查询进行迭代时,无法确定您是否能够在任务超时之前完成整个迭代。其次,我上次检查的
q.count()
,数量限制为1000个实体

我解决这个问题的简单方法是(主要考虑这个psuedo代码):

def\u迭代和索引(游标=无):
query=MyModel.query
q = Database.query()
q.filter(Database.title > None)
numEntities = q.count(limit=50000)
q = Database.query()
q = q.filter(Database.title > None)
numEntities = q.count(limit=50000)