dump_trees.py 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. """Dump 5 棵作用域分类树(PG public.global_category)→ 本地 JSON。
  2. 产物(scope_trees/):
  3. - trees.json 整个分类树,按 source_type 分组(含已退役节点,live 标记)
  4. - trees_index.json 仅 live 节点(scope-link 定位目标),与 trees_embeddings.npy 行对齐
  5. 须在能连 RDS 的环境跑(云端)。用法:python scripts/dump_trees.py [env_file]
  6. """
  7. from __future__ import annotations
  8. import json
  9. import sys
  10. from collections import Counter
  11. from pathlib import Path
  12. from core.config import PgConfig
  13. from core.db import fetch_all
  14. OUT = Path("scope_trees")
  15. def fetch_nodes(cfg: PgConfig) -> list[dict]:
  16. return fetch_all(
  17. cfg,
  18. "SELECT stable_id, name, source_type, path, level, parent_stable_id, "
  19. "(retired_at_execution_id IS NULL) AS live "
  20. "FROM global_category ORDER BY source_type, level, stable_id",
  21. schema="public",
  22. )
  23. def main(env_file: str = ".env") -> None:
  24. cfg = PgConfig.from_env(env_file)
  25. rows = fetch_nodes(cfg)
  26. OUT.mkdir(exist_ok=True)
  27. trees: dict[str, list[dict]] = {}
  28. for r in rows:
  29. trees.setdefault(r["source_type"], []).append({
  30. "stable_id": r["stable_id"], "name": r["name"], "path": r["path"],
  31. "level": r["level"], "parent_stable_id": r["parent_stable_id"],
  32. "live": r["live"],
  33. })
  34. (OUT / "trees.json").write_text(
  35. json.dumps(trees, ensure_ascii=False, indent=2), encoding="utf-8")
  36. live_rows = [r for r in rows if r["live"]]
  37. index = [{
  38. "row": i, "stable_id": r["stable_id"], "source_type": r["source_type"],
  39. "name": r["name"], "path": r["path"],
  40. } for i, r in enumerate(live_rows)]
  41. (OUT / "trees_index.json").write_text(
  42. json.dumps(index, ensure_ascii=False, indent=2), encoding="utf-8")
  43. total = Counter(r["source_type"] for r in rows)
  44. live = Counter(r["source_type"] for r in live_rows)
  45. print("trees.json (全部):", dict(total), "总计", sum(total.values()))
  46. print("trees_index (live):", dict(live), "总计", len(index))
  47. if __name__ == "__main__":
  48. main(sys.argv[1] if len(sys.argv) > 1 else ".env")