Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 多对多关系中的解引用模型_Python_Google App Engine_Many To Many_Dereference_App Engine Ndb - Fatal编程技术网

Python 多对多关系中的解引用模型

Python 多对多关系中的解引用模型,python,google-app-engine,many-to-many,dereference,app-engine-ndb,Python,Google App Engine,Many To Many,Dereference,App Engine Ndb,在我的模式中,如下面的测试数据生成示例所述,我想知道一种好方法: 将具有引用键的收藏夹的所有实例取消引用到已删除图片的实例。只需删除任何链接到已删除图片的收藏夹 Person类是一个用户 Picture类是最受欢迎的课程 favorite类是具有多对多关系的链接模型方式的一个示例 为什么要问这个问题? 首先,我希望它不会超出这里的范围,第二,因为这可能发生,第三,因为它很有趣 怎么做? 假设一个人可以有多达数千个最喜欢的东西,比如喜欢在社交网络上,或者更糟糕的是,在科学应用程序中,订单、帐户

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

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

  • Person
    类是一个用户

  • Picture
    类是最受欢迎的课程

  • favorite
    类是具有多对多关系的链接模型方式的一个示例

为什么要问这个问题? 首先,我希望它不会超出这里的范围,第二,因为这可能发生,第三,因为它很有趣

怎么做? 假设一个人可以有多达数千个最喜欢的东西,比如喜欢在社交网络上,或者更糟糕的是,在科学应用程序中,订单、帐户或无效数据。 在我们的例子中,由于某种原因(这些原因也会发生),一个人正在经历很多死忠链接,或者我确实知道,有死忠链接

要做到这一点,减少
ndb.get()
操作,并且不要在每个收藏夹中迭代

让我们不要把事情复杂化。让我们假设我们只有一个用户受到死宠的折磨。他有一个Person类和stubbed 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数据存储。更多信息:


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

ReferenceProperty只是一个键,因此如果你有被删除人的键,你可以使用它来查询收藏夹


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

您可以使用预删除挂钩(寻找实现它的方法)
当然,如果您使用NDB API而不是数据存储API(),这可能会更容易实现,但是您必须更改引用的方式(谢谢Nizz;-)。我会测试并报告。是的,它只会帮助防止错误链接。如果腐败已经存在……我想不出一个便宜的方法来做到这一点。这就是为什么最好避免这种情况。。。唯一可行的方法(如果您不介意保留损坏的数据,直到看到它们的结果)是在出现时处理错误,即try/except语句,其中您将在try块中有加载部分,在except块中有修复。我确实认为有。例如,如果您只使用密钥,而不使用get进行迭代,但尝试实现联接。我同意,最好的方法是在用户操作时检测到它,并将其添加到任务队列或立即修复它。是的,如果收藏夹是一个小的非昂贵数字,则迭代是最佳方法。但是如果你有50000个收藏夹和99999张图片呢?你必须过滤50000个收藏夹。对于每个收藏夹,请检查图片,如果图片无效,请删除收藏夹。是的,这最终需要花费10万个实体回迁。如果这是一个罕见的(比如说一个月一次或更少)清理操作,那么这并不昂贵。无论怎样,当你删除人物和图片实体时,你都应该清理收藏夹,所以你不需要依赖这种扫描和清理。如果你正在寻找一种更便宜的方法来完成这项工作。。。它不存在(除了预防方法)。你能做的最好的事情就是在“死”收藏夹已经被访问时检查它们(就像用户正在加载页面一样),然后清理它们。然后,您可能不必为了清理而额外读取实体。