【问题标题】:GAE python NDB projection query working in development but not in productionGAE python NDB投影查询在开发中工作但不在生产中
【发布时间】:2019-05-06 12:01:14
【问题描述】:

我一直在碰壁,因为我的 Google App Engine python 项目有一个非常简单的 NDB 投影查询,它在我的本地机器上运行良好,但在部署到生产时却神秘地失败了。

更神秘的是...作为测试,我在另一个属性上添加了相同的投影,它在开发和生产中都有效!有人可以帮忙吗?!以下是更多详细信息:

我有以下代表费用的实体:

class Entry(ndb.Model):
    datetime = ndb.DateTimeProperty(indexed=True, required=True)
    amount = ndb.IntegerProperty(indexed=False, required=True)
    payee = ndb.StringProperty(indexed=True, required=True) 
    comment = ndb.StringProperty(indexed=False)
    # ...

稍后在代码中,我将对 Entry.payee 进行投影(以获取所有收款人的列表)。作为测试,我还在 Entry.datetime 上添加了一个投影:

log_msg = '' # For passing debug info to the browser

payeeObjects = Entry.query(ancestor=exp_traq_key(exp_traq_name), projection=[Entry.payee]).fetch()
payees = []
for obj in payeeObjects:
    payees.append(obj.payee)
log_msg += '%d payees: %s' % (len(payees), str(payees))

log_msg += ' ------------------- ' # a visual separator

dtObjects = Entry.query(ancestor=exp_traq_key(exp_traq_name), projection=[Entry.datetime]).fetch()
dts = []
for obj in dtObjects:
    dts.append(obj.datetime)
log_msg += '%d datetimes: %s' % (len(dts), str(dts))

#...other code, including passing log_msg down to the client

这是开发环境中的输出(注意控制台中显示了收款人列表和日期时间列表):

这是部署到应用引擎时的输出。我无法让它返回收款人列表。即使在 dev 中它可以很好地返回列表,它也会一直返回一个空列表:

我已确保在 GAE 上正确设置了索引:

请帮忙!


2018 年 12 月 5 日更新: 我在生产中添加了更多条目,它们被选中了!见截图。但是较旧的条目仍然没有被退回。

我的直接反应是数据存储索引需要以某种方式“刷新”,以便它可以“看到”旧条目。但问题是我昨天删除并重新创建了索引,这意味着它应该有旧条目......所以仍然需要帮助解决这个谜!

【问题讨论】:

    标签: python google-app-engine google-cloud-datastore projection app-engine-ndb


    【解决方案1】:

    我想通了。该死的根本不直观。我希望 GAE 文档在这一点上做得更好......

    我在生产中的数据存储包含许多以前创建的条目。作为我尝试在 Entry.payee 上进行投影的最新代码的一部分,我不得不将 Entry.payee 的定义从未索引更改为索引,如下所示:

    payee = ndb.StringProperty(indexed=True, required=True) # Originally was indexed=False
    

    所以现在所有位于数据存储中的条目都被投影查询忽略了,因为收款人上的索引忽略了这些条目。

    所以我现在需要做的是以某种方式将所有旧实体迁移到 indexed=True


    更新 - 这是我进行此迁移的方式。结果比预期的要简单。

    def runPayeeTypeMigration(exp_traq_name):
      Entry.query(ancestor=exp_traq_key(exp_traq_name)).fetch()
      for entry in entries:
        entry.put()
    

    这是通过将所有条目读取到更新的数据结构(Entry.payee 被索引=True 的那个)并将其写回数据存储区来实现的,这样实体现在就会被索引。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-20
      • 2011-10-29
      • 1970-01-01
      • 2015-08-05
      相关资源
      最近更新 更多