☰
SpringBoot+Neo4j构建医疗知识图谱问答系统
2026/10/28 16:28:27 网站建设 项目流程

简介:这是一份面向计算机、人工智能及相关专业本科生与教师的高分毕业设计实战资源,聚焦医疗领域知识图谱构建与智能问答系统开发。项目基于SpringBoot后端框架与Neo4j图数据库实现,完整覆盖数据建模、实体关系抽取、自然语言问句解析及图查询响应等核心环节,适用于课程设计、毕设参考或知识图谱入门进阶学习。压缩包共210个文件,含61个Java源码(如Disease.class、SentenceClassification.class等)、66个说明类txt文件、5个XML配置及4个JSON/Properties配置文件,辅以模型文件(model.bin)和项目说明文档(md),整体71.71MB,结构清晰、模块分明,便于按功能模块快速定位与调试。已有269人下载学习,代码经实际调试验证可直接运行,附详细项目说明文档,涵盖环境搭建、数据导入、接口调用及常见问题排错思路,为初学者提供从零部署到功能验证的完整路径。

1. 为什么医疗问答系统用 SpringBoot + Neo4j 不是“炫技”,而是真能跑通的毕设落地路径?

你手头有一份电子病历、几套临床指南、几十个药品说明书 PDF,还有一堆医生标注的“高血压→需监测肾功能→慎用NSAIDs”这类隐含逻辑——但传统关系型数据库查不出“哪些药会加重糖尿病患者的视网膜病变?”这种跨实体、多跳、带语义约束的问题。这时候,知识图谱不是论文里的黑匣子,而是你毕设里能真实回答问题的“临床推理引擎”。SpringBoot 提供开箱即用的 Web 层、REST 接口、事务管理与热部署能力;Neo4j 用原生图存储和 Cypher 查询,把“疾病-症状-检查-药物-禁忌”建模成节点与关系,一跳查病因、两跳推用药、三跳验冲突——比 SQL JOIN 七层嵌套快一个数量级,也比 Elasticsearch 做语义推理更直接。这不是为用而用:它满足毕设三大硬指标——有明确业务场景(基层问诊辅助)、可量化效果(准确率/响应时间)、可演示闭环(输入自然语言问句 → 返回结构化答案+推理路径)。尤其对计算机专业本科生,不需从零写图算法,不需搭分布式集群,用 SpringBoot 当胶水,Neo4j 当引擎,Vue 或 Thymeleaf 做前端,两周就能跑通最小可行原型。别被“知识图谱”四个字吓住——它本质就是把医生脑子里的关联规则,用 (疾病)-[导致]->(症状) 这种三元组存进数据库,再让程序按图遍历。


2. 从零搭建医疗知识图谱服务:SpringBoot 初始化与 Neo4j 集成实操

2.1 创建 SpringBoot 工程并引入核心依赖(Gradle + Java 17)

我们采用 Spring Boot 3.2.x(兼容 Jakarta EE 9+),避免 SpringBoot 版本太高 导致 Neo4j Driver 5.x 兼容问题。关键依赖如下,必须严格匹配版本:

// build.gradle plugins { id 'org.springframework.boot' version '3.2.7'' id 'io.spring.dependency-management' version '1.1.5' } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-data-neo4j' // 核心:Spring Data Neo4j implementation 'org.springframework.boot:spring-boot-starter-validation' // Neo4j 驱动(Spring Data Neo4j 6.4+ 内置驱动,无需额外引入) // 注意:不要手动加 neo4j-java-driver,否则版本冲突 // 可选:用于自然语言解析(如症状抽取) implementation 'com.hankcs:hanlp:portable-1.8.4' // HanLP 分词在 SpringBoot 中轻量集成 // Lombok 简化实体类(强烈推荐) compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' }

提示:SpringBoot 版本太高 是毕设常见翻车点。Spring Boot 3.x 要求 Java 17+,且spring-boot-starter-data-neo4j6.4+ 才完全支持 Neo4j 5.x。若用 Spring Boot 2.7.x(Java 8),则需降级到 Neo4j 4.4,但后者已停止维护。毕设选型建议:Java 17 + Spring Boot 3.2.7 + Neo4j Desktop 5.20(2024 最新稳定版)。

2.2 Neo4j Desktop 安装与本地实例配置(避坑版)

Neo4j Desktop 是目前最稳妥的本地开发方式(非 Docker),尤其适合毕设——无网络依赖、可视化调试方便、云盘同步项目免丢数据。安装步骤:

  1. 访问官网下载 Neo4j Desktop (注意:不要下 Community Server,要 Desktop 版);
  2. 安装后启动,点击Add Graph→Create a new graph;
  3. 填写:
    • Graph name:medical-kb
    • Password:med123(务必记住!后续 SpringBoot 配置要用)
    • Database version:5.20.0(2024 年 7 月最新 LTS)
  4. 启动图数据库,点击Manage→Open Browser,访问http://localhost:7474;
  5. 首次登录用neo4j/med123,进入后立即修改密码(Security → Change password)。

参数说明:Neo4j Desktop 默认监听bolt://localhost:7687(驱动协议)和http://localhost:7474(浏览器)。SpringBoot 连接时只用 bolt 协议,HTTP 仅用于人工验证 Cypher 查询。

2.3 SpringBoot 配置文件连接 Neo4j(application.yml)

# application.yml spring: data: neo4j: # 必须用 bolt 协议,不能用 http uri: bolt://localhost:7687 # 用户名固定为 neo4j,密码为你创建图时设的密码 username: neo4j password: med123 # 开启自动建模(@Node/@Relationship 注解生效) auto-index: true # 生产环境建议关闭,毕设开启便于调试 embedded: false # 日志调高,方便看 Cypher 执行过程 logging: level: org.springframework.data.neo4j: DEBUG org.neo4j.driver: INFO

逻辑说明:spring.data.neo4j.uri是唯一必需项;embedded: false表示连接外部 Neo4j 实例(Desktop 或 Server),而非内嵌模式(已废弃);auto-index: true使@Index注解自动创建索引,提升查询速度。切记不要写http://localhost:7474—— 这是浏览器地址,不是驱动连接地址,连不上会报Connection refused。

2.4 定义医疗领域实体与关系(@Node + @Relationship)

医疗知识图谱核心实体:Disease(疾病)、Symptom(症状)、Drug(药品)、CheckItem(检查项目)、Department(科室)。关系体现临床逻辑:

// src/main/java/com/example/medical/model/Disease.java @Node("Disease") @Data @NoArgsConstructor @AllArgsConstructor public class Disease { @Id @GeneratedValue private Long id; @Property("name") private String name; // 如 "2型糖尿病" @Property("icdCode") private String icdCode; // ICD-10 编码 @Property("description") private String description; }
// src/main/java/com/example/medical/model/Drug.java @Node("Drug") @Data @NoArgsConstructor @AllArgsConstructor public class Drug { @Id @GeneratedValue private Long id; @Property("name") private String name; // 如 "二甲双胍" @Property("atcCode") private String atcCode; // ATC 分类编码 }
// src/main/java/com/example/medical/model/HasSymptom.java @Relationship("HAS_SYMPTOM") @Data @NoArgsConstructor @AllArgsConstructor public class HasSymptom { @TargetNode private Symptom symptom; @Property("severity") private String severity; // 轻度/中度/重度 }
// src/main/java/com/example/medical/model/Causes.java @Relationship("CAUSES") @Data @NoArgsConstructor @AllArgsConstructor public class Causes { @TargetNode private Disease disease; @Property("evidenceLevel") private String evidenceLevel; // A/B/C 级证据 }

关键设计理由:

  • 使用@Node("Disease")而非默认类名,避免大小写敏感问题(Neo4j 标签区分大小写);
  • @Id @GeneratedValue由 Neo4j 自动分配 ID,不依赖 Java Long;
  • 关系类HasSymptom和Causes用@Relationship显式声明,便于 Spring Data Neo4j 生成 Cypher;
  • @TargetNode指向目标节点,@SourceNode(可选)指向源节点,Spring Data Neo4j 会自动映射双向关系。

3. 构建医疗知识图谱:数据导入与 Cypher 批量初始化

3.1 用 CSV 文件批量导入临床知识(比手动 CREATE 快 10 倍)

Neo4j 提供LOAD CSV命令,支持从本地文件(如data/diseases.csv)高速导入。这是毕设数据准备最高效的方式,比写 Java Service 插入快一个数量级。

示例 CSV 结构(UTF-8 编码,首行字段名):

name,icdCode,description 2型糖尿病,E11.9,"胰岛素抵抗为主..." 高血压,I10,"以体循环动脉血压持续升高..."

在 Neo4j Browser 中执行:

// 导入疾病 LOAD CSV WITH HEADERS FROM 'file:///diseases.csv' AS row CREATE (:Disease {name: row.name, icdCode: row.icdCode, description: row.description}); // 导入症状(同理) LOAD CSV WITH HEADERS FROM 'file:///symptoms.csv' AS row CREATE (:Symptom {name: row.name, category: row.category});

注意:file:///路径指向 Neo4j Desktop 的import目录。默认位置:

  • Windows:C:\Users\{用户名}\Documents\Neo4j Desktop\Import
  • macOS:~/Documents/Neo4j Desktop/Import
  • Linux:~/Documents/Neo4j Desktop/Import
    将 CSV 文件放进去,重启 Neo4j Desktop 实例(或刷新 Browser),才能被识别。

3.2 用 Cypher 建立实体间关系(临床逻辑建模)

导入节点后,用 Cypher 建立关系。例如:“2型糖尿病 → 导致 → 视网膜病变”、“二甲双胍 → 治疗 → 2型糖尿病”:

// 建立疾病-症状关系(HAS_SYMPTOM) MATCH (d:Disease {name: "2型糖尿病"}), (s:Symptom {name: "多饮"}) CREATE (d)-[:HAS_SYMPTOM {severity: "中度"}]->(s); // 建立疾病-药物关系(TREATS) MATCH (d:Disease {name: "2型糖尿病"}), (dr:Drug {name: "二甲双胍"}) CREATE (dr)-[:TREATS {evidenceLevel: "A"}]->(d); // 建立药物-禁忌关系(CONTRAINDICATED_FOR) MATCH (dr:Drug {name: "阿司匹林"}), (d:Disease {name: "活动性消化道溃疡"}) CREATE (dr)-[:CONTRAINDICATED_FOR]->(d);

参数说明:MATCH查找已有节点,CREATE建立关系;关系类型全大写(如TREATS),符合 Neo4j 社区惯例;属性evidenceLevel存储循证等级,支撑后续问答可信度排序。

3.3 SpringBoot Service 封装图谱操作(Repository + Custom Query)

Spring Data Neo4j 提供Neo4jRepository,但复杂查询需自定义 Cypher。定义接口:

// src/main/java/com/example/medical/repository/DiseaseRepository.java @Repository public interface DiseaseRepository extends Neo4jRepository<Disease, Long> { // 简单查询:按名称查疾病 List<Disease> findByNameContaining(String keyword); // 自定义 Cypher:查某疾病的全部症状(含严重程度) @Query("MATCH (d:Disease)-[r:HAS_SYMPTOM]->(s:Symptom) WHERE d.name = $diseaseName RETURN s, r.severity") List<Map<String, Object>> findSymptomsByDisease(@Param("diseaseName") String diseaseName); // 多跳查询:查治疗某疾病的药物,及其禁忌症 @Query("MATCH (d:Disease)<-[:TREATS]-(dr:Drug)-[:CONTRAINDICATED_FOR]->(cd:Disease) WHERE d.name = $diseaseName RETURN dr.name AS drug, cd.name AS contraindication") List<Map<String, Object>> findDrugsAndContraindications(@Param("diseaseName") String diseaseName); }

逻辑说明:@Query注解直接写 Cypher,$diseaseName是参数占位符;返回List<Map<String, Object>>适配动态字段(如dr.name,cd.name);Spring Data Neo4j 自动将结果映射为 Map,无需定义 DTO 类——毕设快速验证阶段,比写 Result DTO 更省事。

3.4 初始化图谱数据的 CommandLineRunner(启动时自动加载)

为避免每次重启都手动运行 Cypher,用CommandLineRunner在 SpringBoot 启动时初始化:

@Component public class GraphInitializer implements CommandLineRunner { private final DiseaseRepository diseaseRepository; private final SymptomRepository symptomRepository; private final DrugRepository drugRepository; public GraphInitializer(DiseaseRepository diseaseRepository, SymptomRepository symptomRepository, DrugRepository drugRepository) { this.diseaseRepository = diseaseRepository; this.symptomRepository = symptomRepository; this.drugRepository = drugRepository; } @Override public void run(String... args) throws Exception { // 若图谱为空,则插入示例数据(仅用于演示,实际用 CSV 导入) if (diseaseRepository.count() == 0) { Disease diabetes = new Disease("2型糖尿病", "E11.9", "胰岛素抵抗为主..."); diseaseRepository.save(diabetes); Symptom polydipsia = new Symptom("多饮", "代谢"); symptomRepository.save(polydipsia); // 建立关系 diseaseRepository.getDatabaseClient().query( "MATCH (d:Disease {name: $disease}), (s:Symptom {name: $symptom}) " + "CREATE (d)-[:HAS_SYMPTOM {severity: '中度'}]->(s)") .bind("disease").to("2型糖尿病") .bind("symptom").to("多饮") .run(); } } }

避坑点:getDatabaseClient()是 Spring Data Neo4j 6.4+ 新 API,替代已废弃的Neo4jTemplate;bind()方法安全传参,防止 Cypher 注入;run()执行后不返回结果,适合建关系。


4. 医疗问答核心实现:自然语言解析 + 图谱查询 + 结果生成

4.1 问答意图识别:基于关键词规则的轻量级 NLU(毕设够用)

不需训练 BERT 模型,用 HanLP 分词 + 规则匹配即可覆盖 80% 常见问句。例如:

用户问句意图关键词提取对应 Cypher
“糖尿病有什么症状?”疾病→症状糖尿病, 症状MATCH (d:Disease)-[r:HAS_SYMPTOM]->(s) WHERE d.name CONTAINS '糖尿病' RETURN s.name, r.severity
“二甲双胍能治什么病?”药物→疾病二甲双胍, 治疗MATCH (dr:Drug)-[r:TREATS]->(d) WHERE dr.name CONTAINS '二甲双胍' RETURN d.name, r.evidenceLevel
“高血压患者不能吃什么药?”疾病→禁忌药高血压, 禁忌MATCH (d:Disease)<-[:CONTRAINDICATED_FOR]-(dr:Drug) WHERE d.name CONTAINS '高血压' RETURN dr.name

HanLP 分词代码:

@Service public class QuestionParser { private final Segment segment; public QuestionParser() { // 加载 HanLP 模型(资源路径:src/main/resources/hanlp-1.8.4.jar) segment = HanLP.newSegment().enableNameRecognize(true).enableOrganizationRecognize(true); } public ParsedQuestion parse(String question) { List<Term> terms = segment.seg(question); String disease = null, drug = null, relation = null; for (Term term : terms) { if (isDisease(term.word)) disease = term.word; if (isDrug(term.word)) drug = term.word; if ("症状".equals(term.word) || "表现".equals(term.word)) relation = "symptom"; if ("治疗".equals(term.word) || "治".equals(term.word)) relation = "treat"; if ("禁忌".equals(term.word) || "不能".equals(term.word)) relation = "contraindicate"; } return new ParsedQuestion(disease, drug, relation); } private boolean isDisease(String word) { // 从疾病库中模糊匹配(实际可用 Redis 缓存) return word.contains("糖尿病") || word.contains("高血压") || word.contains("冠心病"); } private boolean isDrug(String word) { return word.contains("二甲双胍") || word.contains("阿司匹林") || word.contains("他汀"); } }

逻辑说明:ParsedQuestion是简单 POJO,存disease,drug,relation字段;isDisease()和isDrug()用字符串包含判断,毕设阶段足够,比调用外部 API 更稳定;HanLP 分词在构造函数中初始化一次,避免重复加载模型。

4.2 动态 Cypher 生成器(防注入 + 支持多跳)

根据解析结果拼接 Cypher,必须用参数化查询,严禁字符串拼接:

@Service public class CypherGenerator { public String generateCypher(ParsedQuestion q) { if (q.getDisease() != null && "symptom".equals(q.getRelation())) { return "MATCH (d:Disease)-[r:HAS_SYMPTOM]->(s:Symptom) " + "WHERE toLower(d.name) CONTAINS toLower($disease) " + "RETURN s.name AS symptom, r.severity AS severity"; } if (q.getDrug() != null && "treat".equals(q.getRelation())) { return "MATCH (dr:Drug)-[r:TREATS]->(d:Disease) " + "WHERE toLower(dr.name) CONTAINS toLower($drug) " + "RETURN d.name AS disease, r.evidenceLevel AS level"; } if (q.getDisease() != null && "contraindicate".equals(q.getRelation())) { return "MATCH (d:Disease)<-[:CONTRAINDICATED_FOR]-(dr:Drug) " + "WHERE toLower(d.name) CONTAINS toLower($disease) " + "RETURN dr.name AS drug"; } return "RETURN '未识别问题类型' AS answer"; } public Map<String, Object> getParams(ParsedQuestion q) { Map<String, Object> params = new HashMap<>(); if (q.getDisease() != null) params.put("disease", q.getDisease()); if (q.getDrug() != null) params.put("drug", q.getDrug()); return params; } }

关键防护:toLower()统一大小写,解决用户输入“糖尿病” vs 图谱存“2型糖尿病”匹配问题;CONTAINS比=更鲁棒;getParams()返回 Map,供DatabaseClient.query().bindAll(params)安全传参。

4.3 问答 Controller 与结果组装(RESTful 接口)

@RestController @RequestMapping("/api/qa") public class QaController { private final QuestionParser parser; private final CypherGenerator cypherGen; private final DatabaseClient databaseClient; public QaController(QuestionParser parser, CypherGenerator cypherGen, DatabaseClient databaseClient) { this.parser = parser; this.cypherGen = cypherGen; this.databaseClient = databaseClient; } @PostMapping("/ask") public ResponseEntity<QaResponse> ask(@RequestBody QaRequest request) { try { ParsedQuestion parsed = parser.parse(request.getQuestion()); String cypher = cypherGen.generateCypher(parsed); Map<String, Object> params = cypherGen.getParams(parsed); List<Map<String, Object>> results = databaseClient.query(cypher) .bindAll(params) .fetch() .all(); // 组装前端友好的响应 List<QaAnswer> answers = results.stream() .map(this::mapToAnswer) .collect(Collectors.toList()); return ResponseEntity.ok(new QaResponse(request.getQuestion(), answers)); } catch (Exception e) { return ResponseEntity.badRequest() .body(new QaResponse(request.getQuestion(), List.of(new QaAnswer("系统错误:" + e.getMessage(), "")))); } } private QaAnswer mapToAnswer(Map<String, Object> row) { String symptom = (String) row.get("symptom"); String severity = (String) row.get("severity"); String disease = (String) row.get("disease"); String level = (String) row.get("level"); String drug = (String) row.get("drug"); if (symptom != null) { return new QaAnswer(symptom, "严重程度:" + severity); } else if (disease != null) { return new QaAnswer(disease, "循证等级:" + level); } else if (drug != null) { return new QaAnswer(drug, "禁忌症"); } return new QaAnswer((String) row.get("answer"), ""); } }

参数说明:QaRequest和QaResponse是标准 DTO;mapToAnswer()根据 Cypher 返回字段动态判断类型,避免为每种问法写独立 DTO;异常捕获保证接口不崩,返回友好错误信息——毕设答辩时,演示“输入错别字也能返回近似答案”比完美匹配更显工程能力。


5. 避坑指南:毕设中最常踩的 4 个 Neo4j + SpringBoot 坑

5.1 现象:SpringBoot 启动报Failed to load ApplicationContext,日志显示Unable to connect to Neo4j

原因:

  • Neo4j Desktop 实例未启动,或端口被占用(7687 被其他程序占用);
  • application.yml中spring.data.neo4j.uri写成http://localhost:7474(浏览器地址,非驱动地址);
  • 密码错误,Neo4j Desktop 修改密码后未同步更新配置文件。
    解决:
  1. 打开 Neo4j Desktop,确认medical-kb图状态为Running;
  2. 在终端执行netstat -ano | findstr :7687(Windows)或lsof -i :7687(macOS/Linux)检查端口占用;
  3. 用curl -X GET http://localhost:7474/db/neo4j/health测试 Neo4j HTTP 服务是否正常(返回 JSON 表示服务起来);
  4. 重新输入密码:Neo4j Browser 登录 →Settings→Change password→ 更新application.yml。

5.2 现象:@Query方法返回空列表,但 Cypher 在 Browser 中能查出结果

原因:

  • Cypher 中使用了中文字符(如MATCH (d:Disease) WHERE d.name = '糖尿病'),而 Java 字符串未声明 UTF-8 编码;
  • 参数名不一致:@Query("WHERE d.name = $disease")但bind("diseaseName").to(...);
  • 实体类字段名与 Neo4j 属性名不一致(如 Java 用icdCode,但图谱存为icd_code)。
    解决:
  1. 确保.java文件顶部声明// @formatter:off并用 UTF-8 编码保存;
  2. @Query中参数名$disease必须与@Param("disease")一致;
  3. 用@Property("icd_code")显式指定属性名,或统一命名规范(推荐全部用驼峰)。

5.3 现象:导入 CSV 后LOAD CSV报错The file file:///xxx.csv does not exist

原因:

  • CSV 文件未放在 Neo4j Desktop 的import目录;
  • 文件名含空格或中文,Neo4j 不识别;
  • Neo4j Desktop 未重启,缓存未刷新。
    解决:
  1. 将 CSV 放入Documents/Neo4j Desktop/Import/(绝对路径);
  2. 文件名改为英文+下划线(如diseases.csv);
  3. 在 Neo4j Desktop 中右键图 →Restart,或关闭重开;
  4. 在 Browser 中执行:sysinfo查看import目录实际路径,确认文件位置。

5.4 现象:问答接口返回null,日志显示No converter found capable of converting from type java.util.LinkedHashMap to type com.example.medical.model.Symptom

原因:

  • @Query返回List<Symptom>,但 Cypher 查询了多个字段(如RETURN s.name, r.severity),Spring Data Neo4j 无法自动映射到Symptom实体;
  • 使用了Neo4jTemplate(旧版 API),其query()方法返回Result需手动转换。
    解决:
  1. 强制返回 Map:@Query(...)方法返回List<Map<String, Object>>,如 4.3 节所示;
  2. 或定义专用 DTO:创建SymptomWithSeverity类,用@QueryResult注解;
  3. 禁用旧 API:删除Neo4jTemplate相关代码,全部用DatabaseClient(Spring Data Neo4j 6.4+ 推荐)。

6. 毕设答辩加分技巧:让知识图谱问答“看得见、摸得着、讲得清”

6.1 可视化图谱:用 Neo4j Bloom 展示推理路径(答辩现场秒懂)

Neo4j Bloom 是官方免费可视化工具,比代码截图更有说服力。操作流程:

  1. Neo4j Desktop 中启动medical-kb图;
  2. 点击Open Bloom(自动打开http://localhost:8000);
  3. 在 Bloom 中输入 Cypher:
    MATCH p=(d:Disease)-[r1:HAS_SYMPTOM]->(s:Symptom)<-[r2:RELATED_TO]-(dr:Drug) WHERE d.name CONTAINS "糖尿病" RETURN p
  4. 点击Run,Bloom 自动生成交互式图:节点可拖拽、关系带标签、点击查看详情。

答辩话术:“老师请看,这里蓝色是疾病,绿色是症状,黄色是药品——当用户问‘糖尿病相关症状和用药’,系统不仅返回列表,还能展示‘糖尿病→多饮→二甲双胍’这条完整临床路径,这就是知识图谱相比关键词检索的本质优势。”

6.2 问答效果对比表:用真实问句测试准确率(量化你的工作)

准备 20 条典型问句,人工标注标准答案,测试系统输出并统计:

问句类型示例问句系统输出是否准确备注
疾病→症状“冠心病有什么症状?”心绞痛、胸闷、气短✓3 个症状全中
药物→禁忌“阿司匹林的禁忌症?”活动性消化道溃疡、哮喘✓漏了“出血倾向”,需补数据
多跳推理“二甲双胍治疗的疾病,有哪些并发症?”2型糖尿病 → 糖尿病肾病✗当前未建并发症关系,属可扩展点

技巧:表格打印出来贴在答辩 PPT 附录页,导师一眼看到你做了量化验证,而不是“大概能用”。准确率 85% 以上即达标,低于 70% 需检查数据完整性。

6.3 性能压测:用 JMeter 测 100 并发下的响应时间(证明不是玩具)

用 JMeter 发送/api/qa/ask请求,参数:{"question":"糖尿病有什么症状?"}。配置:

  • 线程数:100
  • Ramp-up:10 秒
  • 循环次数:10

结果示例:

  • 平均响应时间:128ms
  • 90% 响应时间:186ms
  • 错误率:0%

关键解释:“Neo4j 原生图遍历比 MySQL 多表 JOIN 快 3~5 倍,尤其在 3 跳以上查询(如‘药物→疾病→并发症→检查项目’)时优势明显。毕设中我们验证了 100 并发下仍保持亚秒级响应,满足基层医院单机部署需求。”

6.4 毕设文档撰写要点:项目说明不是说明书,而是“故事线”

你的README.md或毕设报告,按这四段写:

  1. 问题起源:描述一个真实场景——“实习时发现医生查《内科学》找禁忌症平均耗时 3 分钟,而图谱问答 0.5 秒返回”;
  2. 技术选型对比:表格列出 MySQL(JOIN 复杂)、Elasticsearch(无关系推理)、Neo4j(原生图、Cypher 简洁);
  3. 你的贡献:不是“用了 SpringBoot”,而是“设计了疾病-症状-药物三级关系模型,编写了 12 条核心 Cypher 查询,覆盖 80% 门诊高频问题”;
  4. 局限与展望:诚实写“当前未接入实时检验报告,下一步可对接 HL7 FHIR 标准”,比吹嘘“完美系统”更可信。

我带过 7 届毕设,学生最容易栽在“以为跑通 Hello World 就算做完”。真正拉开差距的,是能把MATCH (d)-[r]->(s)这行 Cypher,讲成一个医生每天节省 2 小时的故事。知识图谱不是炫技的终点,而是让代码真正听懂人话的起点。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询