Optimisation de la hiérarchie sur le magasin de données Google Appengine
-
06-07-2019 - |
Question
Les données hiérarchiques stockées dans le magasin de données utilisent un modèle ressemblant à ceci:
class ToolCategories(db.Model):
name = db.StringProperty()
parentKey = db.SelfReferenceProperty(collection_name="parent_category")
...
...
Je souhaite imprimer tous les noms de catégorie en préservant la hiérarchie, par exemple sous une forme semblable à celle-ci:
--Information Gathering
----OS Fingerprinting
----DNS
------dnstool
----Port Scanning
------windows
--------nmap
----DNS3
----wireless sniffers
------Windows
--------Kismet
Pour faire ce qui précède, j'ai utilisé une récursivité simple à l'aide de la fonctionnalité de référencement arrière:
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)
Comme je suis très novice dans la programmation des moteurs d’applications (trois jours à peine depuis que j’ai commencé à écrire du code), je ne sais pas si c’est le moyen le plus optimisé du point de vue de l’accès au magasin de données pour effectuer le travail souhaité.
Est-ce le meilleur moyen? sinon ce qui est?
La solution
Vous avez une approche très raisonnable! Mon avertissement principal est celui qui a peu à voir avec GAE et beaucoup avec Python: ne pas construire une chaîne à partir de morceaux avec +
ou + =
. Au lieu de cela, vous faites une liste de morceaux de chaîne (avec append
ou extend
ou une liste de compréhensions & amp; c) et lorsque vous avez tous terminé, vous le rejoignez pour la chaîne finale. résultat avec ''. join (liste)
ou similaire. Même si les versions récentes de Python s'efforcent d'optimiser les performances intrinsèques O (N carré)
des boucles +
ou + =
, à la fin Il est toujours préférable de constituer des listes de chaînes le long du chemin et ''. Rejoignez-les
en les intégrant à la fin!
Autres conseils
Le principal inconvénient de votre approche est que vous utilisez la " liste de contiguïté " Pour représenter les arbres, vous devez effectuer une requête de banque de données pour chaque branche de l’arbre. Les requêtes de banque de données sont assez coûteuses (environ 160 ms chacune), donc la construction de l'arborescence, particulièrement si elle est volumineuse, pourrait être assez coûteuse).
Il existe une autre approche, qui est essentiellement celle prise par le magasin de données pour représenter les groupes d'entités: au lieu de simplement stocker la clé parente, stockez toute la liste des ancêtres à l'aide d'un ListProperty:
class ToolCategories(db.Model):
name = db.StringProperty()
parents = db.ListProperty(db.Key)
Ensuite, pour construire l’arborescence, vous pouvez récupérer le tout en une seule requête:
q = ToolCategories.all().filter('parents =', root_key)