[英]SQLAlchemy Adjacency List Queries
I'm attempting to create a simple Flask application that models network devices and their membership to arbitrarily-named domains (if it's relevant, the tool will be used to define MPLS LSP meshes between the devices. I'm using sqlite for dev and production will be postgres). 我正在尝试创建一个简单的Flask应用程序,该应用程序可以对网络设备及其隶属任意命名的域的成员进行建模(如果相关,该工具将用于定义设备之间的MPLS LSP网格。我正在使用sqlite进行开发和生产)将是postgres)。 The relationships should go as follows: 关系应该如下:
Here is my model: 这是我的模型:
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)
How can I structure my SQLAlchemy query to start at the device itself and recurse up the tree to get to the given root Domain (with no parents) in order to generate a list of devices in each domain up the tree? 我怎样组织我的SQLAlchemy查询开始在设备本身以及递归上树去,以便生成装置在每个域上树列表中的给定根域(无父母)? As an example: 举个例子:
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()
The goal here is, given switch_1
as an input, how do I get a list of other devices in its domain, plus the devices in its parent domain (and, if it applies in the real world, recurse until I reach its root domain)? 这里的目标是,在以switch_1
作为输入的情况下,如何获取其域中其他设备以及其父域中的设备的列表(并且,如果适用于现实世界,则递归直到我到达其根域) ?
Traversing tree structures can be done using a recursive Common Table Expression in SQL. 遍历树结构可以使用SQL中的递归通用表表达式来完成。 Given your goal to fetch the domain of a device and its possible parent domains, and then all the devices in those domains, you could start by creating a CTE for fetching the domains: 给定您要获取设备域及其可能的父域以及这些域中所有设备的目标,可以从创建用于获取域的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))
And then just fetch the devices that are in the found domains: 然后仅获取找到的域中的设备:
db.session.query(Device).\
join(domain_query, domain_query.c.id == Device.domain_id).\
all()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.