簡體   English   中英

SQLAlchemy鄰接列表查詢

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM