我使用如下所示的模型存储在数据存储区中的分层数据:
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天),我不确定这是否是从Datastore访问角度来看最优化的方式来完成所需的工作。
这是最好的方法吗?如果不是什么?
答案 0 :(得分:4)
您的方法的主要缺点是,因为您使用表示树的“邻接列表”方式,您必须为树的每个分支执行一次数据存储查询。数据存储区查询相当昂贵(每个大约160毫秒),因此构建树,特别是如果它很大,可能相当昂贵)。
还有另一种方法,它基本上是数据存储区用于表示实体组的方法:不是仅存储父键,而是使用ListProperty存储整个祖先列表:
class ToolCategories(db.Model):
name = db.StringProperty()
parents = db.ListProperty(db.Key)
然后,要构建树,您可以在一个查询中检索整个事物:
q = ToolCategories.all().filter('parents =', root_key)
答案 1 :(得分:2)
你有一个非常合理的方法!我的主要注意事项是与GAE关系不大但与Python有很多关系:不要使用+
或+=
来构建字符串。相反,你制作一个字符串片段列表(包括append
或extend
或列表理解&amp; c),当你完成所有这些时,你加入{{1}的最终字符串结果等等。即使最近的Python版本努力优化''.join(thelist)
或O(N squared)
循环的内在+
性能,但最终你总是更好地建立字符串列表并且+=
最后他们了!