How to update one property for multiple NDB entities?

1.2k views Asked by At

I have NDB model class like below:

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

I will have a daily cron job to mark contests with passed end_date with ended equal to True. I've written the following code to do it:

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)

But I don't like it, since I have to read all entities just to update one value. Is there any way to modify it to read keys_only?

2

There are 2 answers

1
Igor Artamonov On BEST ANSWER

The object data overwrites the existing entity. The entire object is sent to Datastore

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

So you cannot send only one field of an entity, it will "remove" all existing fields. To be more accurate - replace an entity with all fields with new version of entity that have only one field.

You have to load all entities you want to update, with all properties, not just keys, set new value of a property, and put back into database.

3
minou On

I think a Python property is a good solution here:

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

    @property
    def ended(self):
        return self.end_date < date.today()

This way you don't ever need to update your entities. The value is automatically computed whenever you need it.