【问题标题】:How to update one property for multiple NDB entities?如何为多个 NDB 实体更新一个属性?
【发布时间】:2015-06-25 12:11:03
【问题描述】:

我有如下 NDB 模型类:

class Contest(ndb.Model):
    end_date = ndb.DateProperty(required=True, indexed=True)
    ended = ndb.BooleanProperty(required=False, indexed=True)
    ...

我将有一个每日 cron 作业来标记通过 end_dateended 等于 True 的比赛。为此,我编写了以下代码:

contests = Contest.query()
current_datetime = datetime.datetime.utcnow()
today = datetime.date(current_datetime.year, current_datetime.month, current_datetime.day)
contests = contests.filter(Contest.end_date < today)
contests = contests.filter(Contest.ended == False)
contests = contests.fetch(limit=10)
for contest in contests:
    contest.ended = True
ndb.put_multi(contests)

但我不喜欢它,因为我必须读取所有实体才能更新一个值。有什么办法可以修改为keys_only

【问题讨论】:

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


    【解决方案1】:

    对象数据覆盖现有实体。整个对象被发送到数据存储区

    https://cloud.google.com/datastore/docs/concepts/entities#Datastore_Updating_an_entity

    所以你不能只发送一个实体的一个字段,它会“删除”所有现有的字段。更准确地说 - 用只有一个字段的新版本实体替换所有字段的实体。

    您必须加载所有要更新的实体,包括所有属性,而不仅仅是键,设置属性的新值,然后放回数据库中。

    【讨论】:

    • 谢谢,伊戈尔。这是否意味着我的方法是最好的(就读/写操作的数量而言)?
    【解决方案2】:

    我认为 Python 属性是一个很好的解决方案:

    class Contest(ndb.Model):
        end_date = ndb.DateProperty(required=True, indexed=True)
    
        @property
        def ended(self):
            return self.end_date < date.today()
    

    这样您就无需更新实体。该值会在您需要时自动计算。

    【讨论】:

    • 谢谢,Kekito。以前从未见过这样的属性。我可以在 NDB 过滤器中使用它的值吗?
    • 否,因为它没有存储在数据存储中。但是,您可以在 end_date 上进行查询以实现相同的目标。
    • GAE 不允许有多个不等式过滤器,所以我不能直接使用end_date,这就是为什么我要实现额外的ended 属性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-03
    • 2017-04-21
    • 1970-01-01
    相关资源
    最近更新 更多