查资料/server.py(attach_links 第 547-560 行、card_full 第 563-574 行、links_of 第 538-544 行)links(a,b) 表)。列表页要显示每张卡的"关联数",天真做法是每张卡查一次数据库——
100 张卡就是 101 次查询。数据一多就明显变慢。
批量 + 邻接表(第 547-560 行):
def attach_links(cards):
"""给卡片列表批量附加关联卡片 id(供列表页显示关联数)。"""
if not cards:
return cards
conn = db()
rows = conn.execute("SELECT a,b FROM links").fetchall() # 一次拿全部关系
conn.close()
m = {}
for r in rows: # 在内存里建无向邻接表
m.setdefault(r["a"], set()).add(r["b"])
m.setdefault(r["b"], set()).add(r["a"])
for c in cards:
c["links"] = sorted(x for x in m.get(c["id"], set()) if x != c["id"])
return cards
单条查关联(无向关系,用 UNION 两个方向,第 538-544 行):
def links_of(cid):
conn = db()
rows = conn.execute(
"SELECT b FROM links WHERE a=? UNION SELECT a FROM links WHERE b=?", (cid, cid)
).fetchall()
conn.close()
return [r[0] for r in rows]
详情页要标题而不只是 id(第 563-574 行):
def card_full(cid):
card = card_by_id(cid)
if not card:
return None
ids = [x for x in links_of(cid) if x != cid]
card["links"] = ids
card["link_cards"] = []
for x in ids:
c = card_by_id(x)
if c:
card["link_cards"].append({"id": x, "title": c["title"]})
return card
UNION:a→b 和 b→a 是同一条,查两个方向才对dict[str, set] 是最简单的图结构,够用且快if x != c["id"] 排除"自己关联自己"db() 连接与 links 表结构(逻辑独立,函数级可改)attach_relations(rows, relation_table, key)selectinload / prefetch_related(一次性预取关联,避免 N+1)第 15 课(结构化输出实战)