💻 源码
"""执行 cypher 节点

输入: state['cypher_query']: List[str]                 要执行的 cypher 语句
输出: state['cypher_results']: List[List[Dict]]        每条语句一份结果

用 neo4j_manager 的 run_cypher 逐条执行,不用 run_multiple_cypher:后者把整批放进一个
写事务,任意一条报错整批回滚,这里是读查询,一条查不出来不该拖掉其他几条的结果。

结果和 cypher_query 下标一一对应,即使某条报错也占一个空列表的位置 —— 下游要靠下标
把结果对回是哪条语句问出来的。
"""

from typing import Any, Dict, List

from _004_langgraph_more_nodes.agent_state import AgentState
from common.neo4j_manager import neo4j_client


def run_cypher_node(state: AgentState) -> AgentState:
    print("cypher执行节点执行开始了")
    cypher_query_list = state.get("cypher_query") or []
    cypher_results: List[List[Dict[str, Any]]] = []

    for cypher_query in cypher_query_list:
        try:
            rows = neo4j_client.run_cypher(cypher_query)
        except Exception as e:
            # 查询本身出错不该让整个图挂掉,记下来给这条占位空结果
            print(f"cypher 执行失败: {cypher_query[:80]}\n  {e}")
            rows = []
        print(f"  {len(rows)} 行 <- {cypher_query[:70]}")
        cypher_results.append(rows)

    state["cypher_results"] = cypher_results
    print(f"完成执行cypher语句: {len(cypher_results)} 条")
    return state


if __name__ == "__main__":
    state = run_cypher_node(
        {
            "cypher_query": [
                "MATCH (h:Herb)-[:HAS_EFFECT]->(e:Effect) WHERE h.name IN ['人参'] "
                "RETURN h.name AS herb, e.name AS effect LIMIT 10",
                "MATCH (f:Formula)-[:HAS_INGREDIENT]->(h:Herb) WHERE f.name = '四君子汤' "
                "RETURN h.name AS herb LIMIT 10",
                "MATCH (s:Source)<-[:FROM_SOURCE]-(f:Formula) WHERE s.name = '《伤寒论》' "
                "RETURN f.name AS formula LIMIT 5",
                # 图里没有的实体:语句合法,预期 0 行
                "MATCH (h:Herb) WHERE h.name = '阿司匹林' RETURN h.name AS herb",
                # 语法错误:预期打印失败并占一个空列表
                "MATC1H (h:Herb) RETURN h.name",
            ]
        }
    )
    for i, rows in enumerate(state["cypher_results"], 1):
        print(f"\n第 {i} 条 -> {len(rows)} 行")
        for row in rows[:5]:
            print(f"  {row}")


    print("======================")
    print(state)