Select recursivo web2py
Neste artigo vamos tratar um assunto um tanto conhecido porém pouco explanado.
Esta dica vale não somente para web2py mas para qualquer outro que precise organizar seus dados em estruturas de arvore usando dados vindos do banco.
db.define_table('thing',
Field('name'),
Field('owner_id', 'reference person'))
A documentação do web2py propõe a seguinte estrutura de tabela e a seguinte forma para fazer um select recursivo nesses dados.
person = db.person(id)
for thing in person.thing.select(orderby=db.thing.name):
print person.name, 'owns', thing.name
O fato é que se fizermos o comando db().select() ele irá criar uma nova conexão com o banco de dados e assim quantas vezes for preciso.
Se pensarmos em um sistema que recebe vários visitantes por minuto (ou segundo), mesmo uma tabela com poucos dados sobrecarregaria nossa aplicação.
Então qual é o ideal?
O ideal sempre será fazer uma única conexão ao banco de dados para pegar tudo que precisamos, então iremos processar estes dados organizando-os em forma de arvore.
Vou usar um algorítimo de pre ordem para varrer a lista de Rows e organizá-los em um dicionário que conterá a estrutura abaixo.
roots = { 1: {'id':1, 'name': 'Paul', 'childreen': {
3: {'id': 3, 'name': 'Jessica', 'childreen': {}
,8: {'id': 8, 'name': 'Robert', 'childreen': {...}
}
Dessa forma podemos aproveitar isto em menus dropdowns, estruturas de arvore entre outros.
Aqui está o algorítimo:
rows = db(db.person).select().as_dict() roots = {}# Pre order algorithm def pre_order(node): for k, v in rows.items(): if node['id'] == v['owner_id']: if 'childreen' not in node: node['childreen'] = {} node['childreen'][k] = v del rows[k] pre_order(v)# Filter fathers for k, v in rows.items(): if v['owner_id']==None: del rows[k] # Now search by son pre_order(v) roots[k] = v
O algorítimo acima combinado com a facilidade do DAL do web2py é uma mão na roda.
Espero ter ajudado e tirado dúvidas.
Valeu T+
Comentários
Postar um comentário