tree_service.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. from __future__ import annotations
  2. from collections.abc import Iterable
  3. from pathlib import Path
  4. from sqlalchemy import text
  5. from examples.demand.db_manager import DatabaseManager
  6. db = DatabaseManager()
  7. def _fmt_node(name: str, level: int | None) -> str:
  8. if level is None:
  9. return f"{name}[L?]"
  10. return f"{name}[L{int(level)}]"
  11. def _fetch_roots_by_name(session, execution_id: int, name: str):
  12. return session.execute(
  13. text(
  14. """
  15. SELECT id, name, level
  16. FROM topic_pattern_category
  17. WHERE execution_id = :execution_id AND name = :name
  18. ORDER BY id
  19. """
  20. ),
  21. {"execution_id": execution_id, "name": name},
  22. ).fetchall()
  23. def _fetch_children_by_parent(session, execution_id: int, parent_id: int):
  24. return session.execute(
  25. text(
  26. """
  27. SELECT id, name, level
  28. FROM topic_pattern_category
  29. WHERE execution_id = :execution_id AND parent_id = :parent_id
  30. ORDER BY id
  31. """
  32. ),
  33. {"execution_id": execution_id, "parent_id": parent_id},
  34. ).fetchall()
  35. def _collect_subtree_lines(
  36. session,
  37. execution_id: int,
  38. node_id: int,
  39. name: str,
  40. level: int | None,
  41. depth: int,
  42. ) -> list[str]:
  43. indent = " " * depth
  44. lines = [f"{indent}{_fmt_node(name, level)}"]
  45. for row in _fetch_children_by_parent(session, execution_id, node_id):
  46. cid, cname, clevel = row[0], row[1], row[2]
  47. lines.extend(
  48. _collect_subtree_lines(session, execution_id, cid, cname, clevel, depth + 1)
  49. )
  50. return lines
  51. def build_category_trees_text(execution_id: int, names: Iterable[str]) -> str:
  52. """
  53. 按 execution_id 与名称列表,在 topic_pattern_category 中从每个 name 对应行出发,
  54. 沿 parent_id 向下遍历整棵子树,返回多棵树拼接的文本(子节点每深一层缩进 2 空格)。
  55. 每行格式:name[L{level}](level 为表字段;若为空则显示 L?)。
  56. 输入列表中的每个 name 输出一块;若同名匹配多行,则该块内为多棵子树,树之间空一行。
  57. 某 name 无匹配时,仅输出一行 name[L?]。
  58. """
  59. clean_names = [str(n).strip() for n in names if n is not None and str(n).strip()]
  60. if not clean_names:
  61. return ""
  62. blocks: list[str] = []
  63. session = db.get_session()
  64. try:
  65. for name in clean_names:
  66. roots = _fetch_roots_by_name(session, execution_id, name)
  67. if not roots:
  68. blocks.append(_fmt_node(name, None))
  69. continue
  70. tree_texts: list[str] = []
  71. for row in roots:
  72. rid, rname, rlevel = row[0], row[1], row[2]
  73. tree_texts.append(
  74. "\n".join(
  75. _collect_subtree_lines(session, execution_id, rid, rname, rlevel, 0)
  76. )
  77. )
  78. blocks.append("\n\n".join(tree_texts))
  79. finally:
  80. session.close()
  81. return "\n\n".join(blocks)
  82. if __name__ == "__main__":
  83. execution_id = 58
  84. names = ["健康养生"
  85. , "公共安全"
  86. , "地标景观"
  87. , "防诈反骗"
  88. , "身体健康"
  89. , "饮食调理"
  90. , "地形水域"
  91. , "建筑地标"
  92. , "自然地标"
  93. , "医疗卫生"
  94. , "综合风光"
  95. , "居家生活"
  96. , "办事指南"
  97. , "政策法规"
  98. , "自然奇景"
  99. , "中医养生"
  100. , "烹饪技巧"
  101. , "安全防护"
  102. , "皮肤护理"
  103. , "地质奇观"
  104. , "社会保障"
  105. , "心理认知"
  106. , "办事规程"
  107. , "养老规划"
  108. , "金融理财"
  109. , "农业农村"
  110. , "补贴福利"
  111. , "禁毒防毒"
  112. , "国家安全"
  113. , "设施安全"]
  114. text_out = build_category_trees_text(execution_id, names)
  115. out_path = Path(__file__).resolve().parent / "new_result" / f"category_tree_{execution_id}.txt"
  116. out_path.parent.mkdir(parents=True, exist_ok=True)
  117. out_path.write_text(text_out, encoding="utf-8")
  118. print(out_path)