0

在我的模式中,如下面的测试数据生成示例所述,我想知道一种好方法:

取消引用所有收藏夹实例,这些实例具有对已删除图片实例的引用键。只需删除链接到已删除图片的任何收藏夹。

  • 该类Person是用户

  • Picture课程可以成为收​​藏夹

  • 该类Favourite是具有多对多关系的链接模型方式的示例。

为什么这么问? 首先,我希望它不会超出这里的范围,其次是因为这可能发生,第三是因为它很有趣。

如何? 假设一个人可以拥有多达数千个收藏夹,例如社交网络上的点赞,或者更糟的是,科学应用程序中的订单、帐户或无效数据。在我们的示例中,由于某种原因(并且这些原因发生),一个人正在经历很多死去的最爱链接,或者我知道,有死去的最爱。

有什么好的方法可以做到这一点,减少 ndb.get()操作而不是遍历每个收藏夹。

让事情不要复杂化。让我们假设我们只有一个用户的最爱。他有一个 Person 类和 '123' 的存根 user_id 属性。

在以下示例中,您可以使用以下处理程序及其相应的函数。

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 数据存储中的最终一致性,单独的处理程序。更多信息: 使用后端 NDB 的 GAE put_multi() 实体

当然,我也发布了一个答案,以表明我在发布之前尝试了一些东西。

4

2 回答 2

1

ReferenceProperty 只是一个键,因此如果您有已删除人员的键,则可以使用它来查询收藏夹。

否则,没有简单的方法。您必须过滤所有收藏夹并找到具有无效图片的收藏夹。这在 mapreduce 作业中非常简单,但如果您有很多收藏夹,这可能是一个昂贵的查询。

于 2012-12-26T17:11:13.750 回答
1

您可以使用预删除钩子(在此处查找实现方法)当然,如果您使用 NDB API 而不是 Datastore API(NDB 上的钩子),这可以更容易完成,但是您必须更改你做参考的方式

于 2012-12-30T04:05:45.953 回答