简体   繁体   English

如何删除NDB数据库的StructuredProperty(或重复属性)中的单个项目?

[英]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. 我有一个ndb.Model,其中包含一个Repeated属性。

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

I put a list of "keys" into "hotel_keys" property. 我将“键”列表放入“ hotel_keys”属性中。 Then I need to delete a single item in it (let's say by id) How could I do that? 然后,我需要删除其中的一个项目(用ID表示),该怎么办?

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. 谢谢。

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) 这是一种无需迭代即可删除并删除的方法:(仅适用于重复的键属性,因为它实际上具有带有单个属性ID的字符串表示形式,对于重复的结构化属性,您将必须循环并检查要删除的属性,以获取get循环后索引并删除)

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()

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. 因此,您可以只使用pop和index而不是循环。 The put() 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> 

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 您应该创建列表的副本,但不包含要删除的值-请参见以下问题: 迭代时从列表中删除项目

I found that using the list's remove() method works well: 我发现使用列表的remove()方法效果很好:

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. 请注意,我在这里使用的是实际的NDB密钥,而不是密钥ID。 This assumes that the hotel_keys property is a list of keys of some other model class , like. 假设hotel_keys属性是其他一些模型类的键的列表,例如。 Like your Resort class should be updated to have: 像您的Resort类应该更新为:

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

And then be sure you have a class Hotel(ndb.Model) defined somewhere. 然后确保在某处定义了一个class Hotel(ndb.Model) 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. 要重申我在上面留下的注释:它将仅弹出该值的1个实例。 If there's a risk your .hotel_keys property has duplicates, be sure to handle that. 如果您的.hotel_keys属性存在重复的风险,请务必进行处理。 I'd use resort.hotel_keys = list(set(resort.hotel_keys)) before getting the index for deletion. 在获取要删除的索引之前,我会使用resort.hotel_keys = list(set(resort.hotel_keys))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM