在我的架构中,如下面的测试数据生成示例所述,我想知道一个好方法:
取消引用具有已删除图片实例的引用键的所有收藏夹实例。只需删除任何链接到已删除图片的收藏夹。
Person
类是用户
Picture
类可以是收藏夹
Favourite
类是具有多对多关系的Link-Model方式的示例。
为什么会这个问题? 首先,我希望它不会超出范围,第二,因为这可能发生,第三,因为它很有趣。
如何吗 假设一个人可以拥有多达数千个收藏夹,例如Likes在社交网络上,或者在科学应用程序中使订单,帐户或无效数据变得更糟。 在我们的例子中出于某种原因(并且这些原因发生),一个人正在经历许多死亡最喜欢的链接,或者我知道,有最喜欢的人。
这样做的好方法是,减少 ndb.get()
操作,不迭代通过每个收藏夹。
不要让事情复杂化。让我们假设我们只有一个用户遭受了死亡的收藏。他有一类Person和stubped user_id属性'123'。
在以下示例中,您可以使用以下处理程序及其相应的功能。
import time
import sys
import logging
import random
import cgi
import webapp2
from google.appengine.ext import ndb
class Person(ndb.Expando):
pass
class Picture(ndb.Expando):
pass
class Favourite(ndb.Expando):
user_id = ndb.StringProperty(required=True)
#picture = ndb.KeyProperty(kind=Picture, required=True)
pass
class GenerateDataHandler(webapp2.RequestHandler):
def get(self):
try:
number_of_models = abs(int(cgi.escape(self.request.get('n'))))
except:
number_of_models = 10
logging.info("GET ?n=parameter not defined. Using default.")
pass
user_id = '123' #stub
person = Person.query().filter(ndb.GenericProperty('user_id') == user_id).get()
if not person:
person = Person()
person.user_id = user_id #Stub
person.put()
logging.info("Created Person instance")
if not self._gen_data(person, number_of_models):
return
self.response.write("Data generated successfully")
def _gen_data(self, person, number_of_models):
first, last = Picture.allocate_ids(number_of_models)
picture_keys = [ndb.Key(Picture, id) for id in range(first, last+1)]
pictures = []
favourites = []
for picture_key in picture_keys:
picture = Picture(key=picture_key)
pictures.append(picture)
favourite = Favourite(parent=person.key,
user_id=person.user_id,
picture=picture_key
)
favourites.append(favourite)
entities = favourites
entities[1:1] = pictures
ndb.put_multi(entities)
return True
class CorruptDataHandler(webapp2.RequestHandler):
def get(self):
if not self._corrupt_data(0.5):#50% corruption
return
self.response.write("Data corruption completed successfully")
def _corrupt_data(self, n):
picture_keys = Picture.query().fetch(99999, keys_only=True)
random_picture_keys = random.sample(picture_keys, int(float(len(picture_keys))*n))
ndb.delete_multi(random_picture_keys)
return True
class FixDataHandler(webapp2.RequestHandler):
def get(self):
user_id = '123' #stub
person = Person.query().filter(ndb.GenericProperty('user_id') == user_id).get()
self._dereference(person)
def _dereference(self, person):
#Here if where you implement your answer
由于最终的一致性而将处理程序分开 NDB数据存储区。更多信息: GAE put_multi() entities using backend NDB
当然,我发布的答案也是为了表明我在发布之前尝试了一些东西。
答案 0 :(得分:1)
ReferenceProperty只是一个键,所以如果你有被删除的Person的键,你可以使用它来查询收藏夹。
否则,没有简单的方法。您必须过滤所有收藏夹并找到具有无效图片的收藏夹。它在mapreduce作业中非常简单,但如果你有很多收藏夹,它可能是一个昂贵的查询。
答案 1 :(得分:1)
您可以使用预删除挂钩(外观here来实现它) 当然,如果您使用NDB API而不是数据存储API(hooks on NDB),这可以更容易地完成,但是您将不得不改变您进行参考的方式