4

我使用如下所示的模型将分层数据存储在数据存储中:

class ToolCategories(db.Model):  
   name = db.StringProperty()  
   parentKey = db.SelfReferenceProperty(collection_name="parent_category")  
   ...  
   ...  

我想打印所有保留层次结构的类别名称,例如以如下形式:

--Information Gathering  
----OS Fingerprinting  
----DNS  
------dnstool  
----Port Scanning   
------windows  
--------nmap  
----DNS3  
----wireless sniffers  
------Windows  
--------Kismet  

为此,我使用了使用反向引用功能的简单递归:

class GetAllCategories (webapp.RequestHandler) :


        def RecurseList(self, object, breaks) :
                output = breaks + object.name + "</br>"
                for cat in object.parent_category:
                        output = output + self.RecurseList(cat, breaks + "--")

                return output



        def get (self) :
                output = ""
                allCategories = ToolCategories.all().filter(' parentKey = ', None)
                for category in allCategories :
                        output = output + self.RecurseList(category, "--")

                self.response.out.write(output)

由于我对 App 引擎编程非常陌生(距离我开始编写代码还不到 3 天),我不确定从数据存储访问的角度来看,这是否是完成所需工作的最优化方式。

这是最好的方法吗?如果不是,那是什么?

4

2 回答 2

4

您的方法的主要缺点是,因为您使用“邻接表”表示树的方式,您必须对树的每个分支进行一次数据存储查询。数据存储查询相当昂贵(每个大约 160 毫秒),因此构建树,特别是如果它很大,可能会相当昂贵)。

还有另一种方法,本质上是数据存储区用来表示实体组的方法:不只是存储父键,而是使用 ListProperty 存储整个祖先列表:

class ToolCategories(db.Model):
  name = db.StringProperty()
  parents = db.ListProperty(db.Key)

然后,要构建树,您可以在一个查询中检索整个事物:

q = ToolCategories.all().filter('parents =', root_key)
于 2009-06-21T12:34:17.907 回答
2

你有一个非常合理的方法!我的主要警告是与 GAE 几乎没有关系,而与 Python 有很大关系:不要+从带有or的片段构建字符串+=。相反,您制作了一个字符串片段列表(使用appendorextend或列表推导 &c),当您完成所有操作后,您将其加入到最终的字符串结果中''.join(thelist)。尽管最近的 Python 版本努力优化or循环的内在O(N squared)性能,但最终你总是最好在此过程中构建字符串列表并在最后完成它们!++=''.join

于 2009-06-21T05:00:24.667 回答