momijigari
momijigari

Reputation: 1598

How to remove a single item in StructuredProperty ( or Repeated Property) of an NDB database?

I have an ndb.Model which contains one Repeated property in it.

class Resort(ndb.Model):
    name        = ndb.StringProperty()
    hotel_keys  = ndb.KeyProperty(repeated=True)

I put a list of "keys" into "hotel_keys" property. Then I need to delete a single item in it (let's say by id) How could I do that?

resort = Resort.get_by_id(resort_id)
for hotel_key in resort.hotel.keys:
     if hotel_key.id() == id:
         del ???
resort.put()

I would appreciate any help. Thanks.

Upvotes: 1

Views: 2120

Answers (4)

hamx0r
hamx0r

Reputation: 4278

I found that using the list's remove() method works well:

if some_hotel_key in resort.hotel_keys:
     resort.hotel_keys.remove(some_hotel_key)
resort.put()

Note that I'm using actual NDB Keys here, not key ID's. This assumes that the hotel_keys property is a list of keys of some other model class, like. Like your Resort class should be updated to have:

hotel_keys = ndb.KeyProperty(kind=Hotel, repeated=True)

And then be sure you have a class Hotel(ndb.Model) defined somewhere. this would then let you define:

some_hotel_key = ndb.Key(Hotel, 'myHotel')

To reiterate a note I left above: it will only pop 1 instance of the value. If there's a risk your .hotel_keys property has duplicates, be sure to handle that. I'd use resort.hotel_keys = list(set(resort.hotel_keys)) before getting the index for deletion.

Upvotes: 0

Tim Hoffman
Tim Hoffman

Reputation: 12986

THe repeated property is just a list, and the entity you are putting in the list is fairly simple. So you can just use pop and index rather than looping. The put()

dev~fish-and-lily> class Resort(ndb.Model):
...    hotel_keys = ndb.KeyProperty(repeated=True)
... 
dev~xxx-and-zzz> y = XX()
dev~xxx-and-zzz> y.hotel_keys.append(ndb.Key('abc',1))
dev~xxx-and-zzz> y.hotel_keys.append(ndb.Key('abc',2))
dev~xxx-and-zzz> y.hotel_keys.append(ndb.Key('abc',3))
dev~xxx-and-zzz> y.hotel_keys.index(ndb.Key('abc',3))
2
dev~xxx-and-zzz> y.hotel_keys.pop(2)
Key('abc', 3)
dev~xxx-and-zzz> y.hotel_keys
[Key('abc', 1), Key('abc', 2)]
dev~xxx-and-zzz> 

Upvotes: 3

Faisal
Faisal

Reputation: 2276

Here is a way to delete it without iteration and remove: (only works for repeated keyproperty since it has an actualy string representation with single property id, for repeated structured property you'll have to loop and check against the property you want to delete get index and delete after the loop)

key_to_delete = ndb.Key(ModelOfThatId, id)

if key_to_delete in resort.hotel_keys:
    idx = resort.hotel_keys.index(key_to_delete)
    del resort.hotel_keys[idx]
    resort.put()

Upvotes: 4

Peter Knego
Peter Knego

Reputation: 80340

Repeated properties are lists and iterating a list and removing a value from it at the same time is not possible. You should create a copy of the list without the value that you want removed - see this question: Remove items from a list while iterating

Upvotes: 2

Related Questions