[英]SQLAlchemy Adjacency List Queries
我正在嘗試創建一個簡單的Flask應用程序,該應用程序可以對網絡設備及其隸屬任意命名的域的成員進行建模(如果相關,該工具將用於定義設備之間的MPLS LSP網格。我正在使用sqlite進行開發和生產)將是postgres)。 關系應該如下:
這是我的模型:
class Device(db.Model):
__tablename__ = 'device'
id = db.Column(db.Integer, primary_key=True)
hostname = db.Column(db.String(255), unique=True)
mgmt_ip = db.Column(db.String(255), unique=True)
snmp_comm = db.Column(db.String(255))
domain_id = db.Column(db.Integer, db.ForeignKey('domain.id'))
def __repr__(self):
return '<Hostname %r>' % (self.hostname)
class Domain(db.Model):
__tablename__ = 'domain'
id = db.Column(db.Integer, primary_key=True)
parent_id = db.Column(db.Integer, db.ForeignKey('domain.id'))
name = db.Column(db.String(255), unique=True)
children = db.relationship("Domain")
devices = db.relationship("Device")
def __repr__(self):
return '<Domain %r>' % (self.name)
我怎樣組織我的SQLAlchemy查詢開始在設備本身以及遞歸上樹去,以便生成裝置在每個域上樹列表中的給定根域(無父母)? 舉個例子:
from app import db
from app.models import Device, Domain
db.create_all()
d1 = Domain(name='mandatory')
db.session.add(d1)
db.session.commit()
d2 = Domain(name='metro_A', parent_id=1)
db.session.add(d2)
db.session.commit()
d3 = Domain(name='metro_B', parent_id=1)
db.session.add(d3)
db.session.commit()
dev1 = Device(hostname='switch_1', mgmt_ip='1.1.1.1', snmp_comm='public', domain_id=1)
dev2 = Device(hostname='switch_2', mgmt_ip='2.2.2.2', snmp_comm='public', domain_id=1)
dev3 = Device(hostname='switch_3', mgmt_ip='3.3.3.3', snmp_comm='public', domain_id=2)
dev4 = Device(hostname='switch_4', mgmt_ip='4.4.4.4', snmp_comm='public', domain_id=2)
dev5 = Device(hostname='switch_5', mgmt_ip='5.5.5.5', snmp_comm='public', domain_id=3)
dev6 = Device(hostname='switch_6', mgmt_ip='6.6.6.6', snmp_comm='public', domain_id=3)
db.session.add_all([dev1, dev2, dev3, dev4, dev5, dev6])
db.session.commit()
這里的目標是,在以switch_1
作為輸入的情況下,如何獲取其域中其他設備以及其父域中的設備的列表(並且,如果適用於現實世界,則遞歸直到我到達其根域) ?
遍歷樹結構可以使用SQL中的遞歸通用表表達式來完成。 給定您要獲取設備域及其可能的父域以及這些域中所有設備的目標,可以從創建用於獲取域的CTE開始:
domain_alias = db.aliased(Domain)
# Domain of switch_1 has no parents, so for demonstration switch_6
# is a better target.
initial = db.session.query(Domain.id, Domain.parent_id).\
join(Device).\
filter_by(hostname='switch_6').\
cte(recursive=True)
child = db.aliased(initial)
domain_query = initial.union(
db.session.query(domain_alias.id, domain_alias.parent_id).
join(child, child.c.parent_id == domain_alias.id))
然后僅獲取找到的域中的設備:
db.session.query(Device).\
join(domain_query, domain_query.c.id == Device.domain_id).\
all()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.