集成知识图谱到项目中

dev_2.1.0
liu 1 year ago
parent 90025163a7
commit 6ff12672e8

@ -19,6 +19,13 @@
</properties>
<dependencies>
<dependency>
<groupId>org.nebula-contrib</groupId>
<artifactId>ngbatis</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>com.supervision</groupId>
<artifactId>virtual-patient-model</artifactId>
@ -60,7 +67,7 @@
<dependency>
<groupId>com.vesoft</groupId>
<artifactId>client</artifactId>
<version>3.0.0</version>
<version>3.6.0</version>
</dependency>
<dependency>

@ -7,7 +7,7 @@ import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableScheduling
@SpringBootApplication
@SpringBootApplication(scanBasePackages = {"com.supervision", "org.nebula"})
@MapperScan(basePackages = {"com.supervision.**.mapper"})
@EnableNeo4jRepositories("com.**.repo")
public class VirtualPatientGraphApplication {

@ -0,0 +1,22 @@
package com.supervision.annotations;
// Copyright (c) 2022 All project authors. All rights reserved.
//
// This source code is licensed under Apache 2.0 License.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author yeweicheng
* @since 2022-11-29 22:19
* <br>Now is history!
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValueType {
Class<?> value();
}

@ -0,0 +1,38 @@
package com.supervision.config;
// Copyright (c) 2022 All project authors. All rights reserved.
//
// This source code is licensed under Apache 2.0 License.
import com.supervision.annotations.ValueType;
import com.vesoft.nebula.Value;
import org.nebula.contrib.ngbatis.binding.Setter;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.math.BigDecimal;
/**
* @author yeweicheng
* @since 2022-11-29 20:38
* <br> Now is history!
*/
@Component
public class BigDecimalSetter implements Setter<BigDecimal> {
@Override
public Object set(BigDecimal param) {
return param.doubleValue();
}
public Object set(BigDecimal param, Field field) {
ValueType annotation = field.getAnnotation(ValueType.class);
Class<?> valueType = annotation.value();
return valueType == Byte.class ? Value.iVal(param.byteValue())
: valueType == Short.class ? Value.iVal(param.shortValue())
: valueType == Integer.class ? Value.iVal(param.intValue())
: valueType == Long.class ? Value.iVal(param.longValue())
: valueType == Float.class ? Value.fVal(param.floatValue())
: Value.fVal(param.doubleValue());
}
}

@ -0,0 +1,26 @@
package com.supervision.config;
// Copyright (c) 2022 All project authors. All rights reserved.
//
// This source code is licensed under Apache 2.0 License.
import org.nebula.contrib.ngbatis.PkGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
*
*
* @author yeweicheng
* @since 2022-06-14 12:32
* <br>Now is history!
*/
@Configuration
public class PkGeneratorConfig {
@Bean
public PkGenerator pkGenerator() {
return new SnowflakePKGenerator();
}
}

@ -0,0 +1,16 @@
package com.supervision.config;
import cn.hutool.core.util.IdUtil;
import org.nebula.contrib.ngbatis.PkGenerator;
public class SnowflakePKGenerator implements PkGenerator {
@Override
@SuppressWarnings("all")
public <T> T generate(String tagName, Class<T> pkType) {
if (pkType == String.class) {
return (T) IdUtil.getSnowflakeNextIdStr();
}
return (T) Long.valueOf(IdUtil.getSnowflakeNextIdStr());
}
}

@ -0,0 +1,30 @@
package com.supervision.controller;
import com.supervision.service.GraphNebulaService;
import io.swagger.annotations.Api;
import lombok.RequiredArgsConstructor;
import org.nebula.contrib.ngbatis.models.data.NgSubgraph;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Api(tags = "Nebula图谱")
@RestController("nebulaGraph")
@RequiredArgsConstructor
public class GraphNebulaController {
private final GraphNebulaService graphNebulaService;
@GetMapping("createGraph")
public void createGraph(String processId) {
graphNebulaService.creatGraphByNebula(processId);
}
@GetMapping("queryGraph")
public List<NgSubgraph<String>> queryGraph(String processId) {
return graphNebulaService.queryGraph(processId);
}
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.AllergyHistoryVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface AllergyHistoryDao extends NebulaDaoBasic<AllergyHistoryVertex, String> {
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.AncillaryVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface AncillaryDao extends NebulaDaoBasic<AncillaryVertex, String> {
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.AncillaryResultVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface AncillaryResultDao extends NebulaDaoBasic<AncillaryResultVertex, String> {
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.DiagnosisVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface DiagnosisDao extends NebulaDaoBasic<DiagnosisVertex, String> {
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.FamilyHistoryVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface FamilyHistoryDao extends NebulaDaoBasic<FamilyHistoryVertex, String> {
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.IllnessHistoryVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface IllnessHistoryDao extends NebulaDaoBasic<IllnessHistoryVertex, String> {
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.MarriageChildHistoryVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface MarriageChildHistoryDao extends NebulaDaoBasic<MarriageChildHistoryVertex, String> {
}

@ -0,0 +1,13 @@
package com.supervision.dao;
import com.supervision.domain.MedicalRecVertex;
import org.nebula.contrib.ngbatis.models.data.NgSubgraph;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface MedicalRecDao extends NebulaDaoBasic<MedicalRecVertex, String> {
List<NgSubgraph<String>> selectSubgraph(@Param("processGraphId") String medicalRecVid);
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.OperationHistoryVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface OperationHistoryDao extends NebulaDaoBasic<OperationHistoryVertex, String> {
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.PatientVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface PatientDao extends NebulaDaoBasic<PatientVertex, String> {
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.PersonalHistoryVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface PersonalHistoryDao extends NebulaDaoBasic<PersonalHistoryVertex, String> {
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.PhysicalVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface PhysicalDao extends NebulaDaoBasic<PhysicalVertex, String> {
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.PhysicalResultVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface PhysicalResultDao extends NebulaDaoBasic<PhysicalResultVertex, String> {
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.PreviousHistoryVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface PreviousHistoryDao extends NebulaDaoBasic<PreviousHistoryVertex, String> {
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.ProcessMedicalVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface ProcessMedicalDao extends NebulaDaoBasic<ProcessMedicalVertex, String> {
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.SelfDescVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface SelfDescDao extends NebulaDaoBasic<SelfDescVertex, String> {
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.SymptomsVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface SymptomsDao extends NebulaDaoBasic<SymptomsVertex, String> {
}

@ -0,0 +1,7 @@
package com.supervision.dao;
import com.supervision.domain.TreatmentPlanVertex;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface TreatmentPlanDao extends NebulaDaoBasic<TreatmentPlanVertex, String> {
}

@ -0,0 +1,21 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Data
@Table(name = "allergy_history")
public class AllergyHistoryVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,19 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Data
@Table(name = "ancillary_result")
public class AncillaryResultVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,19 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Data
@Table(name = "ancillary")
public class AncillaryVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,19 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* ()
*/
@Data
@Table(name = "diagnosis")
public class DiagnosisVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,19 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Data
@Table(name = "family_history")
public class FamilyHistoryVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,19 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Data
@Table(name = "illness_history")
public class IllnessHistoryVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,19 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Data
@Table(name = "marriage_child_history")
public class MarriageChildHistoryVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,17 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
@Data
@Table(name = "medical_rec")
public class MedicalRecVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,14 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Table;
/**
*
*/
@Data
@Table(name = "no_property_edge")
public class NoPropertyEdge {
}

@ -0,0 +1,19 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Data
@Table(name = "operation_history")
public class OperationHistoryVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,19 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Data
@Table(name = "patient")
public class PatientVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,19 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Data
@Table(name = "personal_history")
public class PersonalHistoryVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,19 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Data
@Table(name = "physical_result")
public class PhysicalResultVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,19 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Data
@Table(name = "physical")
public class PhysicalVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,19 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Data
@Table(name = "previous_history")
public class PreviousHistoryVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,16 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
@Data
@Table(name = "process_medical")
public class ProcessMedicalVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,16 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
@Data
@Table(name = "process_medical")
public class SelfDescVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,20 @@
package com.supervision.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Table;
/**
*
*/
@Data
@Table(name = "single_property_edge")
@NoArgsConstructor
@AllArgsConstructor
public class SinglePropertyEdge {
private String name;
}

@ -0,0 +1,19 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Data
@Table(name = "symptoms")
public class SymptomsVertex {
@Id
private String id;
private String name;
}

@ -0,0 +1,19 @@
package com.supervision.domain;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Data
@Table(name = "treatment_plan")
public class TreatmentPlanVertex {
@Id
private String id;
private String name;
}

@ -5,8 +5,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.List;
/**
* @author fulin
*/
@ -16,13 +14,13 @@ import java.util.List;
@Data
public class NebulaGraphProperties {
private String userName;
private String username;
private String password;
/**
* ip:prot
*/
private List<String> hostAddresses;
private String hosts;
private int minConnSize;

@ -17,10 +17,11 @@ public class NebulaSession {
@Bean
public Session session() throws Exception {
String[] hostArray = nebulaGraphProperties.getHosts().split(",");
SessionPool sessionPool = new SessionPool(nebulaGraphProperties.getMaxConnSize(),
nebulaGraphProperties.getMinConnSize(),
nebulaGraphProperties.getHostAddresses().get(0),
nebulaGraphProperties.getUserName(),
nebulaGraphProperties.getHosts(),
nebulaGraphProperties.getUsername(),
nebulaGraphProperties.getPassword());
return sessionPool.borrow();
}

@ -37,7 +37,7 @@ public class SpaceController {
@PostMapping("/create")
@ApiOperation("创建图谱")
public List<CommonVo> createSpace(@RequestBody GraphCreateSpace graphCreateSpace) {
public String createSpace(@RequestBody GraphCreateSpace graphCreateSpace) {
return spaceService.createSpace(graphCreateSpace);
}

@ -2,7 +2,6 @@ package com.supervision.nebula.controller;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.supervision.nebula.service.GraphCommonService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@ -23,8 +22,8 @@ public class SubGraphController {
@ApiOperation("子图查询")
public JSONObject querySubGraph() {
String subgraphQuery = "use subgraph;GET SUBGRAPH 100 STEPS FROM \"player101\" YIELD VERTICES AS `vertices_`, EDGES AS `edges_`;";
String s = graphCommonService.executeJson(subgraphQuery);
return JSONUtil.parseObj(s);
// return JSONUtil.parseObj(s);
return null;
}
}

@ -2,7 +2,7 @@ package com.supervision.nebula.controller;
import com.supervision.nebula.dto.graph.GraphCreateIndex;
import com.supervision.nebula.dto.graph.GraphCreateTagEdge;
import com.supervision.nebula.dto.graph.GraphCreateTag;
import com.supervision.nebula.service.GraphCommonService;
import com.supervision.nebula.util.NebulaUtil;
import com.supervision.nebula.vo.CommonVo;
@ -28,10 +28,16 @@ public class TagEdgeController {
@Autowired
GraphCommonService graphCommonService;
@PostMapping("/createTagEdge")
@ApiOperation("创建tag 或者 edge")
public List<CommonVo> createTagEdge(@RequestBody GraphCreateTagEdge graphCreateTagEdge) {
return graphCommonService.executeJson(NebulaUtil.createTagEdge(graphCreateTagEdge), CommonVo.class);
@PostMapping("/createTag")
@ApiOperation("创建tag")
public List<CommonVo> createTagEdge(@RequestBody GraphCreateTag graphCreateTag) {
return graphCommonService.executeJson(NebulaUtil.createTag(graphCreateTag), CommonVo.class);
}
@PostMapping("/createEdge")
@ApiOperation("创建edge")
public List<CommonVo> createEdge(@RequestBody GraphCreateTag graphCreateTag) {
return graphCommonService.executeJson(NebulaUtil.createEdge(graphCreateTag), CommonVo.class);
}

@ -1,8 +1,8 @@
package com.supervision.nebula.controller;
import com.supervision.nebula.dto.graph.GraphCreateVertex;
import com.supervision.nebula.dto.graph.GraphDeleteVertex;
import com.supervision.nebula.dto.graph.GraphInsertVertex;
import com.supervision.nebula.service.GraphCommonService;
import com.supervision.nebula.util.NebulaUtil;
import com.supervision.nebula.vo.CommonVo;
@ -30,9 +30,9 @@ public class VertexManageController {
@PostMapping("/createVertex")
@ApiOperation("创建点(需要附加标签tag信息)")
public List<CommonVo> createVertex(@RequestBody GraphCreateVertex graphCreateVertex) {
String vidType = graphCommonService.getVidType(graphCreateVertex.getSpace());
return graphCommonService.executeJson(NebulaUtil.createPoint(graphCreateVertex, vidType), CommonVo.class);
public List<CommonVo> createVertex(@RequestBody GraphInsertVertex graphInsertVertex) {
String vidType = graphCommonService.getVidType(graphInsertVertex.getSpace());
return graphCommonService.executeJson(NebulaUtil.insertVertex(graphInsertVertex, vidType), CommonVo.class);
}
@PostMapping("/deleteVertex")

@ -1,24 +0,0 @@
package com.supervision.nebula.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @ClassName: UserDto
*/
@Data
@ApiModel("用户入参")
@NoArgsConstructor
@AllArgsConstructor
public class UserDto {
@ApiModelProperty(value = "用户名", required = true, example = "test")
private String username;
@ApiModelProperty(value = "密码", required = true, example = "test")
private String password;
}

@ -14,7 +14,7 @@ import java.util.List;
@AllArgsConstructor
@Builder
@ApiModel("创建tag edge入参")
public class GraphCreateTagEdge {
public class GraphCreateEdge {
/**
*

@ -0,0 +1,36 @@
package com.supervision.nebula.dto.graph;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel("创建tag edge入参")
public class GraphCreateTag {
/**
*
**/
@ApiModelProperty(value = "空间名称", example = "flceshi")
private String space;
@ApiModelProperty(value = "tag/edge名称", example = "demo")
private String tagEdgeName;
@ApiModelProperty(value = "tag/edge描述", example = "备注")
private String tagEdgeComment;
@ApiModelProperty(value = "属性集合")
private List<PropertyBean> propertyList;
@ApiModelProperty(value = "颜色")
private String color;
}

@ -0,0 +1,24 @@
package com.supervision.nebula.dto.graph;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel("删除空间实体")
public class GraphDeleteSpace {
/**
*
**/
@ApiModelProperty(value = "空间名称", example = "flceshi", required = true)
private String space;
}

@ -14,7 +14,7 @@ import java.util.List;
@AllArgsConstructor
@Builder
@ApiModel("创建点入参")
public class GraphCreateVertex {
public class GraphInsertVertex {
/**
*
@ -27,11 +27,9 @@ public class GraphCreateVertex {
@ApiModelProperty(value = "标签tag属性集合", required = false)
private List<String> tagList;
/**
* pointkey
**/
@ApiModelProperty(value = "点的VID", required = true)
private Object pointKey;
private Object tagVid;
@ApiModelProperty(value = "标签tag的属性值集合", required = false)
private List<Object> tagValueList;

@ -19,8 +19,6 @@ public class GraphVertexTatsQuery extends PageBeanDto {
@ApiModelProperty(value = "空间名称", example = "flceshi", required = true)
private String space;
//@ApiModelProperty(value = "标签集合", required = false)
//private List<String> tagList;
@ApiModelProperty(value = "标签", required = false)
private String tag;

@ -29,6 +29,7 @@ public class GraphCommonService {
try {
log.info("执行 executeJson 方法gql={}", gql);
final String data = session.executeJson(gql);
log.info("执行 executeJson 方法,返回结果:{}", data);
final JSONObject jsonObject = JSONUtil.parseObj(data);
// 查询语句异常分析, 根据 json 返回结果解析 error 节点信息
final JSONObject error0 = jsonObject.getJSONArray("errors").getJSONObject(0);
@ -46,16 +47,6 @@ public class GraphCommonService {
}
}
public String executeJson(String gql) {
try {
log.info("执行 executeJson 方法gql={}", gql);
return session.executeJson(gql);
} catch (IOErrorException e) {
log.error("executeJson ql[{}] error, msg [{}]", gql, e.getMessage());
throw new GraphExecuteException("execute gql error, gql: " + gql, e);
}
}
public String getVidType(String space) {
List<AttributeVo> spaceList = executeJson(NebulaUtil.showAttributeInfo(GraphShowInfo.builder()
.attribute("space").attributeName(space).space(space).build()), AttributeVo.class);

@ -3,6 +3,7 @@ package com.supervision.nebula.service;
import cn.hutool.core.collection.CollectionUtil;
import com.supervision.nebula.constant.AttributeEnum;
import com.supervision.nebula.dto.graph.GraphCreateSpace;
import com.supervision.nebula.dto.graph.GraphDeleteSpace;
import com.supervision.nebula.dto.graph.GraphShowAttribute;
import com.supervision.nebula.dto.graph.GraphShowInfo;
import com.supervision.nebula.util.NebulaUtil;
@ -24,8 +25,14 @@ public class SpaceService {
private final GraphCommonService graphCommonService;
public List<CommonVo> createSpace(GraphCreateSpace graphCreateSpace) {
return graphCommonService.executeJson(NebulaUtil.createSpace(graphCreateSpace), CommonVo.class);
public String createSpace(GraphCreateSpace graphCreateSpace) {
graphCommonService.executeJson(NebulaUtil.createSpace(graphCreateSpace), CommonVo.class);
// 执行成功之后,查询图空间名称
return graphCreateSpace.getSpace();
}
public void dropSpace(GraphDeleteSpace graphDeleteSpace) {
graphCommonService.executeJson(NebulaUtil.dropSpace(graphDeleteSpace), CommonVo.class);
}
public List<DetailSpace> detailSpace(GraphShowAttribute graphShowAttribute) {

@ -29,6 +29,9 @@ public class VertexService {
private final GraphCommonService graphCommonService;
/**
*
*/
public List<NebulaVertexJsonResult> vertexList(String space) {
return graphCommonService.executeJson(NebulaUtil.queryMatch(space), NebulaVertexJsonResult.class);
}

@ -57,13 +57,27 @@ public class NebulaUtil {
* @Param [graphCreateSpace]
**/
public static String createSpace(GraphCreateSpace graphCreateSpace) {
String createSpace = String.format("CREATE SPACE `%s` (partition_num = %s, replica_factor = %s,vid_type = %s %s) COMMENT = '%s'",
// 如果没有,分区默认为1
if (ObjectUtil.isEmpty(graphCreateSpace.getReplicaFactor())) {
graphCreateSpace.setReplicaFactor(1);
}
// 如果没有,分片默认为10
if (ObjectUtil.isEmpty(graphCreateSpace.getPartitionNum())) {
graphCreateSpace.setPartitionNum(10);
}
String createSpace = String.format("CREATE SPACE IF NOT EXISTS `%s` (partition_num = %s, replica_factor = %s,vid_type = %s %s) COMMENT = '%s'",
graphCreateSpace.getSpace(), graphCreateSpace.getPartitionNum(), graphCreateSpace.getReplicaFactor(), graphCreateSpace.getFixedType(),
graphCreateSpace.getSize(), graphCreateSpace.getComment());
log.info("创建空间-gql语句:{}", createSpace);
return createSpace;
}
public static String dropSpace(GraphDeleteSpace graphDeleteSpace) {
String deleteSpace = String.format("DROP SPACE IF EXISTS `%s` ", graphDeleteSpace.getSpace());
log.info("删除空间-gql语句:{}", deleteSpace);
return deleteSpace;
}
/**
* @return java.lang.String
* @Description
@ -92,15 +106,20 @@ public class NebulaUtil {
* @Description tag
* @Param [graphCreateTag]
**/
public static String createTagEdge(GraphCreateTagEdge graphCreateTagEdge) {
StringBuffer stringBuffer = new StringBuffer();
List<PropertyBean> propertyList = graphCreateTagEdge.getPropertyList();
public static String createTag(GraphCreateTag graphCreateTag) {
StringBuilder stringBuffer = new StringBuilder();
List<PropertyBean> propertyList = graphCreateTag.getPropertyList();
if (CollectionUtil.isNotEmpty(propertyList)) {
for (int i = 0; i < propertyList.size(); i++) {
PropertyBean propertyBean = propertyList.get(i);
stringBuffer.append(" `" + propertyBean.getPropertyName() + "` " + propertyBean.getPropertyType() + " " +
"" + propertyBean.getIsNull() + " " + propertyBean.getDefaultValue() + " COMMENT '" + propertyBean.getPropertyComment() + "' ");
stringBuffer.append(" `")
.append(propertyBean.getPropertyName())
.append("` ").append(propertyBean.getPropertyType())
.append(" ").append(propertyBean.getIsNull())
.append(" ").append(propertyBean.getDefaultValue())
.append(" COMMENT '").append(propertyBean.getPropertyComment())
.append("' ");
if (propertyList.size() > 1 && (i + 1) != propertyList.size()) {
stringBuffer.append(",");
}
@ -109,8 +128,42 @@ public class NebulaUtil {
String bufferString = stringBuffer.toString();
log.info("stringBuffer :{}", bufferString);
String createTag = "USE `" + graphCreateTagEdge.getSpace() + "`;CREATE " + graphCreateTagEdge.getType() + " `" + graphCreateTagEdge.getTagEdgeName() + "` " +
"( " + bufferString + " ) COMMENT = '" + graphCreateTagEdge.getTagEdgeComment() + "' ";
String createTag = "USE `" + graphCreateTag.getSpace() + "`;CREATE TAG" + " `" + graphCreateTag.getTagEdgeName() + "` " +
"( " + bufferString + " ) COMMENT = '" + graphCreateTag.getTagEdgeComment() + "' ";
log.info("创建Tag-gql语句:{}", createTag);
return createTag;
}
/**
* @return java.lang.String
* @Description edge
* @Param [graphCreateTag]
**/
public static String createEdge(GraphCreateTag graphCreateTag) {
StringBuilder stringBuffer = new StringBuilder();
List<PropertyBean> propertyList = graphCreateTag.getPropertyList();
if (CollectionUtil.isNotEmpty(propertyList)) {
for (int i = 0; i < propertyList.size(); i++) {
PropertyBean propertyBean = propertyList.get(i);
stringBuffer.append(" `")
.append(propertyBean.getPropertyName())
.append("` ").append(propertyBean.getPropertyType())
.append(" ").append(propertyBean.getIsNull())
.append(" ").append(propertyBean.getDefaultValue())
.append(" COMMENT '").append(propertyBean.getPropertyComment())
.append("' ");
if (propertyList.size() > 1 && (i + 1) != propertyList.size()) {
stringBuffer.append(",");
}
}
}
String bufferString = stringBuffer.toString();
log.info("stringBuffer :{}", bufferString);
String createTag = "USE `" + graphCreateTag.getSpace() + "`;CREATE EDGE" + " `" + graphCreateTag.getTagEdgeName() + "` " +
"( " + bufferString + " ) COMMENT = '" + graphCreateTag.getTagEdgeComment() + "' ";
log.info("创建Tag-gql语句:{}", createTag);
return createTag;
}
@ -118,33 +171,33 @@ public class NebulaUtil {
/**
* @return java.lang.String
* @Description
* @Param [graphCreateVertex]
* @Param [graphInsertVertex]
**/
public static String createPoint(GraphCreateVertex graphCreateVertex, String vidType) {
List<Object> tagValueList = graphCreateVertex.getTagValueList();
public static String insertVertex(GraphInsertVertex graphInsertVertex, String vidType) {
List<Object> tagValueList = graphInsertVertex.getTagValueList();
StringBuffer stringBuffer = getStringBuffer(tagValueList);
String bufferString = stringBuffer.toString();
log.info("stringBuffer :{}", bufferString);
StringBuffer stringBufferTagList = new StringBuffer();
List<String> tagList = graphCreateVertex.getTagList();
StringBuilder stringBufferTagList = new StringBuilder();
List<String> tagList = graphInsertVertex.getTagList();
if (CollectionUtil.isNotEmpty(tagList)) {
for (int i = 0; i < tagList.size(); i++) {
String tagPropertyName = tagList.get(i);
stringBufferTagList.append(" `" + tagPropertyName + "` ");
stringBufferTagList.append(" `").append(tagPropertyName).append("` ");
if (tagList.size() > 1 && (i + 1) != tagList.size()) {
stringBufferTagList.append(",");
}
}
}
Object pointKey = graphCreateVertex.getPointKey();
Object tagVid = graphInsertVertex.getTagVid();
if (vidType.contains("STRING")) {
pointKey = "'" + StringEscapeUtils.unescapeHtml(pointKey.toString()) + "'";
tagVid = "'" + StringEscapeUtils.unescapeHtml(tagVid.toString()) + "'";
}
String createPoint = String.format("USE `%s`;INSERT VERTEX IF NOT EXISTS `%s`(%s) VALUES %s: (" + bufferString + ");"
, graphCreateVertex.getSpace(), graphCreateVertex.getTagName(), stringBufferTagList,
pointKey);
, graphInsertVertex.getSpace(), graphInsertVertex.getTagName(), stringBufferTagList,
tagVid);
log.info("创建vertex-gql语句:{}", createPoint);
return createPoint;
}
@ -193,11 +246,11 @@ public class NebulaUtil {
**/
public static String delAttributeProperty(GraphDelAttribute graphDelAttribute) {
StringBuffer stringBuffer = new StringBuffer();
StringBuilder stringBuffer = new StringBuilder();
List<String> propertyNameList = graphDelAttribute.getPropertyNameList();
for (int i = 0; i < propertyNameList.size(); i++) {
String value = propertyNameList.get(i);
stringBuffer.append("`" + value + "`");
stringBuffer.append("`").append(value).append("`");
if (propertyNameList.size() > 1 && (i + 1) != propertyNameList.size()) {
stringBuffer.append(",");
}
@ -229,17 +282,17 @@ public class NebulaUtil {
* @Param [tagList, space] ,
**/
public static String queryMatch(List<String> tagList, String space) {
StringBuffer stringBuffer = new StringBuffer();
StringBuilder stringBuffer = new StringBuilder();
for (int i = 0; i < tagList.size(); i++) {
String tag = tagList.get(i);
stringBuffer.append("MATCH (v:`" + tag + "`) RETURN v limit " + Integer.MAX_VALUE + "");
stringBuffer.append("MATCH (v:`").append(tag).append("`) RETURN v limit ").append(Integer.MAX_VALUE);
if (tagList.size() > 1 && (i + 1) != tagList.size()) {
stringBuffer.append(" UNION ");
}
}
String bufferString = stringBuffer.toString();
log.info("bufferString: {}", bufferString);
String queryMatch = String.format("USE `%s`; " + bufferString + "", space);
String queryMatch = String.format("USE `%s`; " + bufferString, space);
log.info("match查询 -gql语句:{}", queryMatch);
return queryMatch;
}
@ -309,7 +362,7 @@ public class NebulaUtil {
dstVid = "'" + dstVid.toString() + "'";
}
StringBuffer stringBufferEdge = new StringBuffer();
StringBuilder stringBufferEdge = new StringBuilder();
for (String edge : graphInsertEdge.getEdgeList()) {
stringBufferEdge.append("`").append(edge).append("`").append(",");
}
@ -383,7 +436,7 @@ public class NebulaUtil {
* @Param [graphExpand]
**/
public static String expandQuery(GraphExpand graphExpand, String vidType) {
StringBuffer stringBuffer = new StringBuffer();
StringBuilder stringBuffer = new StringBuilder();
List<String> edgeList = graphExpand.getEdgeList();
for (int i = 0; i < edgeList.size(); i++) {
String edge = edgeList.get(i);
@ -399,7 +452,12 @@ public class NebulaUtil {
List<String> leftAndRight = EdgeDirectionEnum.getLeftAndRight(graphExpand.getDirection());
String expandQuery = String.format("USE `%s`;MATCH p=(v) %s- [e " + bufferString + " * %s %s]-%s (v2) WHERE id(v) IN [%s] %s RETURN p LIMIT " + graphExpand.getResultSize() + ";",
graphExpand.getSpace(), leftAndRight.get(0), graphExpand.getStepStart(), graphExpand.getStepEndResult(), leftAndRight.get(1), graphExpand.getVidList(vidType), StringEscapeUtils.unescapeHtml(graphExpand.getCondition()));
graphExpand.getSpace(), leftAndRight.get(0),
graphExpand.getStepStart(),
graphExpand.getStepEndResult(),
leftAndRight.get(1),
graphExpand.getVidList(vidType),
StringEscapeUtils.unescapeHtml(graphExpand.getCondition()));
log.info("扩展查询 -gql语句:{}", expandQuery);
return expandQuery;
}
@ -546,7 +604,7 @@ public class NebulaUtil {
public static <T> PageInfo<T> startPage(List<T> list, Integer pageNum, Integer pageSize) {
//创建Page类
Page page = new Page(pageNum, pageSize);
Page<T> page = new Page<>(pageNum, pageSize);
//为Page类中的total属性赋值
page.setTotal(list.size());
//计算当前需要显示的数据下标起始值
@ -555,8 +613,7 @@ public class NebulaUtil {
//从链表中截取需要显示的子链表并加入到Page
page.addAll(list.subList(startIndex, endIndex));
//以Page创建PageInfo
PageInfo pageInfo = new PageInfo<>(page);
return pageInfo;
return new PageInfo<>(page);
}
/**
@ -571,7 +628,7 @@ public class NebulaUtil {
if (tagList.size() != tagValueList.size()) {
return "";
}
StringBuffer stringBuffer = new StringBuffer();
StringBuilder stringBuffer = new StringBuilder();
for (int i = 0; i < tagList.size(); i++) {
String tag = tagList.get(i);
Object tagValue = tagValueList.get(i);
@ -645,7 +702,7 @@ public class NebulaUtil {
if (edgeList.size() != edgeValueList.size()) {
return "";
}
StringBuffer stringBuffer = new StringBuffer();
StringBuilder stringBuffer = new StringBuilder();
for (int i = 0; i < edgeList.size(); i++) {
String tag = edgeList.get(i);
Object tagValue = edgeValueList.get(i);
@ -756,9 +813,8 @@ public class NebulaUtil {
* @Param [tag, word]
**/
public static String fullQuery(String tag, String word) {
String fullQuery = String.format("LOOKUP ON `%s` WHERE WILDCARD(`%s`.name, \"*%s*\") YIELD id(vertex)"
return String.format("LOOKUP ON `%s` WHERE WILDCARD(`%s`.name, \"*%s*\") YIELD id(vertex)"
, tag, tag, word);
return fullQuery;
}
/**
@ -785,14 +841,14 @@ public class NebulaUtil {
List<Object> srcVidList = graphVertexPathQuery.getSrcVid();
List<Object> dstVidList = graphVertexPathQuery.getDstVid();
String srcVid = "";
String dstVid = "";
StringBuilder srcVid = new StringBuilder();
StringBuilder dstVid = new StringBuilder();
if (vidType.contains("STRING")) {
for (Object id : srcVidList) {
srcVid += "\"" + id.toString() + "\"" + ",";
srcVid.append("\"").append(id.toString()).append("\"").append(",");
}
for (Object id : dstVidList) {
dstVid += "\"" + id.toString() + "\"" + ",";
dstVid.append("\"").append(id.toString()).append("\"").append(",");
}
}
@ -872,10 +928,12 @@ public class NebulaUtil {
**/
public static String commonNeighbor(String space, List<Object> ids) {
StringBuffer stringBuffer = new StringBuffer();
StringBuilder stringBuffer = new StringBuilder();
for (int i = 0; i < ids.size(); i++) {
if (i + 1 < ids.size()) {
stringBuffer.append(" UNION GO FROM '" + ids.get(i) + "' OVER * REVERSELY YIELD src(edge) as id) INTERSECT(GO FROM '" + ids.get(i + 1) + "' OVER * YIELD dst(edge) as id ");
stringBuffer.append(" UNION GO FROM '").append(ids.get(i))
.append("' OVER * REVERSELY YIELD src(edge) as id) INTERSECT(GO FROM '")
.append(ids.get(i + 1)).append("' OVER * YIELD dst(edge) as id ");
}
}
log.info(stringBuffer.toString());
@ -885,6 +943,9 @@ public class NebulaUtil {
return commonNeighbor;
}
/**
* row ids 1
*/
public static String findPathList(String space, List<String> row, List<Object> ids, String vidType) {
String str = JSONUtil.toJsonStr(row);
String idsStr = JSONUtil.toJsonStr(ids);

@ -21,7 +21,4 @@ public class DetailSpace {
@ApiModelProperty("边类型个数")
private Integer edgesNum;
//@ApiModelProperty("空间备注")
//private String spaceComment;
}

@ -0,0 +1,13 @@
package com.supervision.service;
import org.nebula.contrib.ngbatis.models.data.NgSubgraph;
import java.util.List;
public interface GraphNebulaService {
void creatGraphByNebula(String processId);
List<NgSubgraph<String>> queryGraph(String processId);
}

@ -0,0 +1,246 @@
package com.supervision.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.supervision.dao.*;
import com.supervision.domain.*;
import com.supervision.exception.BusinessException;
import com.supervision.model.Process;
import com.supervision.model.*;
import com.supervision.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nebula.contrib.ngbatis.models.data.NgSubgraph;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Slf4j
@Service
@RequiredArgsConstructor
public class GraphNebulaServiceImpl implements GraphNebulaService {
private final ProcessService processService;
private final TreatmentPlanRecordService treatmentPlanRecordService;
private final ProcessMedicalService processMedicalService;
private final MedicalRecService medicalRecService;
private final DiagnosisPrimaryService diagnosisPrimaryService;
private final DiagnosisAncillaryRecordService diagnosisAncillaryRecordService;
private final DiagnosisPhysicalRecordService diagnosisPhysicalRecordService;
private final ConfigPhysicalToolService configPhysicalToolService;
private final ConfigPhysicalLocationService configPhysicalLocationService;
private final ConfigAncillaryItemService configAncillaryItemService;
private final DiseaseService diseaseService;
private final DiagnosisPrimaryRelationService diagnosisPrimaryRelationService;
@Resource
private MedicalRecDao medicalRecDao;
@Resource
private ProcessMedicalDao processMedicalDao;
@Resource
private SelfDescDao selfDescDao;
@Resource
private IllnessHistoryDao illnessHistoryDao;
@Resource
private PersonalHistoryDao personalHistoryDao;
@Resource
private AllergyHistoryDao allergyHistoryDao;
@Resource
private PreviousHistoryDao previousHistoryDao;
@Resource
private FamilyHistoryDao familyHistoryDao;
@Resource
private OperationHistoryDao operationHistoryDao;
@Resource
private PatientDao patientDao;
@Resource
private PhysicalDao physicalDao;
@Resource
private AncillaryDao ancillaryDao;
@Resource
private DiagnosisDao diagnosisDao;
@Resource
private AncillaryResultDao ancillaryResultDao;
@Override
public void creatGraphByNebula(String processId) {
Process process = Optional.ofNullable(processService.getById(processId)).orElseThrow(() -> new BusinessException("未找到流程,创建图谱失败"));
// 根据processId找到对应的诊疗计划,如果没有找到,说明治疗流程未完成,诊断失败
List<TreatmentPlanRecord> treatmentPlanRecordList = treatmentPlanRecordService.lambdaQuery().eq(TreatmentPlanRecord::getProcessId, processId).list();
Assert.notEmpty(treatmentPlanRecordList, () -> new BusinessException("治疗计划为空,请先完成治疗计划"));
Integer disposalMethod = treatmentPlanRecordList.stream().findAny().orElseThrow(() -> new BusinessException("治疗计划为空,请先完成治疗计划")).getDisposalMethod();
// 首先创建一个病历
MedicalRecVertex medicalRecVertex = new MedicalRecVertex();
medicalRecVertex.setName((disposalMethod == 0 ? "门诊" : "住院") + "(" + DateUtil.format(process.getCreateTime(), "yyyy-MM-dd") + ")");
medicalRecDao.insert(medicalRecVertex);
log.info("病历图谱ID:{}", medicalRecVertex.getId());
// 根据processId找到电子病历
ProcessMedical processMedical = processMedicalService.lambdaQuery().eq(ProcessMedical::getProcessId, processId).oneOpt().orElseThrow(() -> new BusinessException("未找到电子病历"));
ProcessMedicalVertex processMedicalVertex = new ProcessMedicalVertex();
processMedicalVertex.setName("病历(" + DateUtil.format(processMedical.getCreateTime(), "yyyy-MM-dd") + ")");
processMedicalDao.insert(processMedicalVertex);
medicalRecDao.insertEdge(medicalRecVertex, new NoPropertyEdge(), processMedicalVertex);
// 创建主诉节点
if (StrUtil.isNotBlank(processMedical.getPatientSelfDesc())) {
SelfDescVertex selfDescVertex = new SelfDescVertex();
selfDescVertex.setName("主诉:" + processMedical.getPatientSelfDesc());
selfDescDao.insert(selfDescVertex);
// 保存节点之间的关系
processMedicalDao.insertEdge(processMedicalVertex, new NoPropertyEdge(), selfDescVertex);
}
// 创建现病史节点
if (StrUtil.isNotBlank(processMedical.getIllnessHistory())) {
IllnessHistoryVertex illnessHistoryVertex = new IllnessHistoryVertex();
illnessHistoryVertex.setName("现病史:" + processMedical.getIllnessHistory());
illnessHistoryDao.insert(illnessHistoryVertex);
// 保存节点之间的关系
processMedicalDao.insertEdge(processMedicalVertex, new NoPropertyEdge(), illnessHistoryVertex);
}
// 创建个人史节点
if (StrUtil.isNotBlank(processMedical.getPersonalHistory())) {
PersonalHistoryVertex personalHistoryVertex = new PersonalHistoryVertex();
personalHistoryVertex.setName("个人史:" + processMedical.getPersonalHistory());
personalHistoryDao.insert(personalHistoryVertex);
// 保存节点之间的关系
processMedicalDao.insertEdge(processMedicalVertex, new NoPropertyEdge(), personalHistoryVertex);
}
// 创建过敏史节点
if (ObjectUtil.isNotEmpty(processMedical.getAllergyHistoryFlag()) && 1 == processMedical.getAllergyHistoryFlag() && StrUtil.isNotBlank(processMedical.getAllergyHistory())) {
AllergyHistoryVertex allergyHistoryVertex = new AllergyHistoryVertex();
allergyHistoryVertex.setName("过敏史:" + processMedical.getAllergyHistory());
allergyHistoryDao.insert(allergyHistoryVertex);
// 保存节点之间的关系
processMedicalDao.insertEdge(processMedicalVertex, new NoPropertyEdge(), allergyHistoryVertex);
}
// 创建既往史节点
if (ObjectUtil.isNotEmpty(processMedical.getPreviousHistoryFlag()) && 1 == processMedical.getPreviousHistoryFlag() && StrUtil.isNotBlank(processMedical.getPreviousHistory())) {
PreviousHistoryVertex previousHistoryVertex = new PreviousHistoryVertex();
previousHistoryVertex.setName("既往史:" + processMedical.getPreviousHistory());
previousHistoryDao.insert(previousHistoryVertex);
// 保存节点之间的关系
processMedicalDao.insertEdge(processMedicalVertex, new NoPropertyEdge(), previousHistoryVertex);
}
// 创建家族史节点
if (ObjectUtil.isNotEmpty(processMedical.getFamilyHistoryFlag()) && 1 == processMedical.getFamilyHistoryFlag() && StrUtil.isNotBlank(processMedical.getFamilyHistory())) {
FamilyHistoryVertex familyHistoryVertex = new FamilyHistoryVertex();
familyHistoryVertex.setName("家族史:" + processMedical.getFamilyHistory());
familyHistoryDao.insert(familyHistoryVertex);
// 保存节点之间的关系
processMedicalDao.insertEdge(processMedicalVertex, new NoPropertyEdge(), familyHistoryVertex);
}
// 创建手术史节点
if (ObjectUtil.isNotEmpty(processMedical.getOperationHistory()) && 1 == processMedical.getOperationHistoryFlag() && StrUtil.isNotBlank(processMedical.getOperationHistory())) {
OperationHistoryVertex operationHistoryVertex = new OperationHistoryVertex();
operationHistoryVertex.setName("手术史:" + processMedical.getOperationHistory());
operationHistoryDao.insert(operationHistoryVertex);
// 保存节点之间的关系
processMedicalDao.insertEdge(processMedicalVertex, new NoPropertyEdge(), operationHistoryVertex);
}
// 创建患者节点
MedicalRec medicalRec = Optional.ofNullable(medicalRecService.getById(process.getMedicalRecId())).orElseThrow(() -> new BusinessException("未找到病历"));
PatientVertex patientVertex = new PatientVertex();
patientVertex.setName("患者:" + medicalRec.getPatientName());
patientDao.insert(patientVertex);
processMedicalDao.insertEdge(medicalRecVertex, new NoPropertyEdge(), patientVertex);
// 创建体格检查节点(physicalId不为空,即为只查配置了检查结果的结果)
List<DiagnosisPhysicalRecord> physicalRecordList = diagnosisPhysicalRecordService.lambdaQuery()
.isNotNull(DiagnosisPhysicalRecord::getPhysicalId)
.eq(DiagnosisPhysicalRecord::getProcessId, processId).list();
Map<String, PhysicalVertex> physicalConfirmMap = new HashMap<>();
for (DiagnosisPhysicalRecord physicalRecord : physicalRecordList) {
ConfigPhysicalTool tool = configPhysicalToolService.getById(physicalRecord.getToolId());
ConfigPhysicalLocation location = null;
if (StrUtil.isNotBlank(physicalRecord.getLocationId())) {
location = configPhysicalLocationService.getById(physicalRecord.getLocationId());
}
if (ObjectUtil.isNotEmpty(tool)) {
PhysicalVertex physicalVertex = new PhysicalVertex();
physicalVertex.setName("体格检查:" + tool.getToolName() + (location != null ? location.getLocationName() : ""));
physicalDao.insert(physicalVertex);
processMedicalDao.insertEdge(medicalRecVertex, new NoPropertyEdge(), physicalVertex);
// 如果是证实诊断依据,添加到证实诊断依据里面去
if (NumberUtil.equals(1, physicalRecord.getBasisConfirmFlag())) {
physicalConfirmMap.put(physicalRecord.getId(), physicalVertex);
}
}
}
// 创建辅助检查节点
List<DiagnosisAncillaryRecord> ancillaryRecordList = diagnosisAncillaryRecordService.lambdaQuery()
.isNotNull(DiagnosisAncillaryRecord::getAncillaryId)
.eq(DiagnosisAncillaryRecord::getProcessId, processId).list();
Map<String, AncillaryVertex> ancillaryConfirmMap = new HashMap<>();
for (DiagnosisAncillaryRecord diagnosisAncillaryRecord : ancillaryRecordList) {
ConfigAncillaryItem configAncillaryItem = configAncillaryItemService.getById(diagnosisAncillaryRecord.getItemId());
if (ObjectUtil.isNotEmpty(configAncillaryItem)) {
AncillaryVertex ancillaryVertex = new AncillaryVertex();
ancillaryVertex.setName("辅助检查:" + configAncillaryItem.getItemName());
ancillaryDao.insert(ancillaryVertex);
// 保存病历和辅助检查连线
medicalRecDao.insertEdge(medicalRecVertex, new NoPropertyEdge(), ancillaryVertex);
// 结果节点
AncillaryResultVertex ancillaryResultVertex = new AncillaryResultVertex();
ancillaryResultVertex.setName(diagnosisAncillaryRecord.getResult());
ancillaryResultDao.insert(ancillaryResultVertex);
// 保存检查结果连线
ancillaryDao.insertEdge(ancillaryVertex, new SinglePropertyEdge("结果"), ancillaryResultVertex);
// 如果是证实诊断依据,添加到证实诊断依据里面去
if (NumberUtil.equals(1, diagnosisAncillaryRecord.getBasisConfirmFlag())) {
ancillaryConfirmMap.put(diagnosisAncillaryRecord.getId(), ancillaryVertex);
}
}
}
// 创建诊断节点(这个诊断是最终诊断)
List<DiagnosisPrimary> diagnosisPrimaryList = diagnosisPrimaryService.lambdaQuery().eq(DiagnosisPrimary::getProcessId, processId).eq(DiagnosisPrimary::getExcludeFlag, 1).list();
Map<String, DiagnosisVertex> diagnosisMap = new HashMap<>();
for (DiagnosisPrimary diagnosisPrimary : diagnosisPrimaryList) {
Disease disease = diseaseService.getById(diagnosisPrimary.getPrimaryDiagnosisId());
if (ObjectUtil.isNotEmpty(disease)) {
DiagnosisVertex diagnosisVertex = new DiagnosisVertex();
diagnosisVertex.setName("诊断:" + disease.getDiseaseNameAlias());
diagnosisDao.insert(diagnosisVertex);
diagnosisDao.insertEdge(medicalRecVertex, new SinglePropertyEdge("诊断"), diagnosisVertex);
diagnosisMap.put(diagnosisPrimary.getId(), diagnosisVertex);
}
}
// 获取诊断和体格检查及辅助检查之间的关联关系
List<DiagnosisPrimaryRelation> relationList = diagnosisPrimaryRelationService.lambdaQuery().eq(DiagnosisPrimaryRelation::getProcessId, processId).list();
for (DiagnosisPrimaryRelation relation : relationList) {
// 根据关系找到对应的疾病诊断节点
DiagnosisVertex diagnosisVertex = diagnosisMap.get(relation.getPrimaryId());
if (ObjectUtil.isNotEmpty(diagnosisVertex)) {
// 如果疾病诊断不为空,则根据relationId,查询对应的体格检查节点
PhysicalVertex physicalVertex = physicalConfirmMap.get(relation.getRelationId());
if (ObjectUtil.isNotEmpty(physicalVertex)) {
physicalDao.insertEdge(diagnosisVertex, new SinglePropertyEdge("依据"), physicalVertex);
}
// 再尝试找辅助检查
AncillaryVertex ancillaryVertex = ancillaryConfirmMap.get(relation.getRelationId());
if (ObjectUtil.isNotEmpty(ancillaryVertex)) {
ancillaryDao.insertEdge(diagnosisVertex, new SinglePropertyEdge("依据"), ancillaryVertex);
}
}
}
log.info("病历图谱ID:{}", medicalRecVertex.getId());
processService.lambdaUpdate().set(Process::getGraphId, medicalRecVertex.getId()).eq(Process::getId, processId).update();
}
@Override
public List<NgSubgraph<String>> queryGraph(String processId) {
Process process = Optional.ofNullable(processService.getById(processId)).orElseThrow(() -> new BusinessException("未找到对应的问诊流程"));
return medicalRecDao.selectSubgraph(process.getGraphId());
}
}

@ -24,7 +24,7 @@ spring:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.10.138:3306/virtual_patient_test?useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true&serverTimezone=GMT%2B8
url: jdbc:mysql://192.168.10.137:3306/virtual_patient?useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true&serverTimezone=GMT%2B8
username: root
password: '123456'
initial-size: 5 # 初始化大小
@ -56,13 +56,41 @@ spring:
username: neo4j
password: 123456
nebula:
userName: root
password: nebula
hostAddresses: [ 10.0.64.106:9669 ]
ngbatis:
use-session-pool: true
# 127.0.0.1:9669, ip:port, ....
hosts: 192.168.10.137:9669
username: root
password: 123456
# 注意,新建使用的时候,必须有一个库
space: virtual_patient
# http客户端使用
minConnSize: 5
maxConnSize: 10
timeout: 300000
idleTime: 180000
# ngbatis使用连接池配置
pool-config:
# 连接池中最小空闲连接数
min-conns-size: 0
# 连接池中最大空闲连接数
max-conns-size: 10
# 客户端同服务端建立连接的超时时间设置,单位为 ms超过设定时间未建立起连接则报错
timeout: 0
# 连接空闲时间,为 0 表示连接永不删除,单位为 ms
idle-time: 0
# 连接池检测空闲连接的时间间隔,为 -1 表示不进行检测
interval-idle: -1
# 连接等候时间,超过则不再等候连接
wait-time: 0
# 集群允许最小的服务可用率1.0 表示为所有机器 graphd 可用0.25 表示集群中 1/4 机器可用即可
min-cluster-health-rate: 1.0
# 是否允许 SSL 连接,目前暂不支持
enable-ssl: false
cql:
parser:
# 更换开发者自定义的 xml 所在位置
mapper-locations: nebulaMapper/**/*.xml # 默认为 mapper/**/*.xml
# nebula上传文件使用
path:
uploadFilePath: /opt/project/java/graphFile
@ -73,5 +101,9 @@ mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
logging:
level:
org.nebula.contrib: DEBUG

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.AllergyHistoryDao">
</mapper>

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.AncillaryDao">
</mapper>

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.AncillaryResultDao">
</mapper>

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.DiagnosisDao">
</mapper>

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.FamilyHistoryDao">
</mapper>

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.IllnessHistoryDao">
</mapper>

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.MarriageChildHistoryDao">
</mapper>

@ -0,0 +1,7 @@
<mapper namespace="com.supervision.dao.MedicalRecDao">
<select id="selectSubgraph" resultType="org.nebula.contrib.ngbatis.models.data.NgSubgraph">
GET SUBGRAPH WITH PROP 100 STEPS FROM '${processGraphId}' YIELD VERTICES AS nodes, EDGES AS relationships
</select>
</mapper>

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.OperationHistoryDao">
</mapper>

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.PatientDao">
</mapper>

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.PersonalHistoryDao">
</mapper>

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.PhysicalDao">
</mapper>

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.PhysicalResultDao">
</mapper>

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.PreviousHistoryDao">
</mapper>

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.ProcessMedicalDao">
</mapper>

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.SelfDescDao">
</mapper>

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.SymptomsDao">
</mapper>

@ -0,0 +1,3 @@
<mapper namespace="com.supervision.dao.TreatmentPlanDao">
</mapper>

@ -0,0 +1,53 @@
DROP SPACE IF EXISTS virtual_patient; // 如果存在先删除图空间
CREATE SPACE IF NOT EXISTS virtual_patient (vid_type=FIXED_STRING(64)) comment= "虚拟病人"; // 创建图空间
USE virtual_patient; // 切换图空间
// 创建病历节点
CREATE TAG IF NOT EXISTS medical_rec(name String);
// 创建电子病历节点
CREATE TAG IF NOT EXISTS process_medical(name string);
// 创建主诉节点
CREATE TAG IF NOT EXISTS self_desc(name string);
// 创建既往病史节点
CREATE TAG IF NOT EXISTS previous_history(name string);
// 创建现病史节点
CREATE TAG IF NOT EXISTS illness_history(name string);
// 创建个人史节点
CREATE TAG IF NOT EXISTS personal_history(name string);
// 创建过敏史节点
CREATE TAG IF NOT EXISTS allergy_history(name string);
// 创建家族史节点
CREATE TAG IF NOT EXISTS family_history(name string);
// 创建婚育史节点
CREATE TAG IF NOT EXISTS marriage_child_history(name string);
// 创建手术史节点
CREATE TAG IF NOT EXISTS operation_history(name string);
// 创建症状节点
CREATE TAG IF NOT EXISTS symptoms(name string);
// 创建患者信息节点
CREATE TAG IF NOT EXISTS patient(name string);
// 创建体格检查节点
CREATE TAG IF NOT EXISTS physical(name string);
// 创建体格检查结果节点
CREATE TAG IF NOT EXISTS physical_result(name string);
// 创建辅助检查节点
CREATE TAG IF NOT EXISTS ancillary(name string);
// 创建辅助检查结果节点
CREATE TAG IF NOT EXISTS ancillary_result(name string);
// 创建处置节点
CREATE TAG IF NOT EXISTS treatment_plan(name string);
// 创建诊断(疾病)节点
CREATE TAG IF NOT EXISTS diagnosis(name string);
// 创建无属性的边
CREATE EDGE IF NOT EXISTS no_property_edge();
// 创建单个属性的边
CREATE EDGE IF NOT EXISTS single_property_edge(name string);
// 创建病历索引
CREATE TAG INDEX medical_rec_index ON medical_rec (name(64))

@ -0,0 +1,35 @@
package com.supervision;
import cn.hutool.core.io.FileUtil;
import java.io.File;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
public class GenerateXml {
public static void main(String[] args) {
String sourcePath = "/Users/flevance/Java/virtual-patient/virtual-patient-graph/src/main/java/com/supervision/dao";
String targetPath = "/Users/flevance/Java/virtual-patient/virtual-patient-graph/src/main/resources/nebulaMapper/";
String packageName = "com.supervision.dao.";
List<String> sourceFileList = FileUtil.listFileNames(sourcePath);
for (String sourceFile : sourceFileList) {
String newFileName = sourceFile.replace(".java", ".xml");
/**
* <mapper namespace="com.supervision.dao.MedicalRecDao">
*
* </mapper>
*/
if (!FileUtil.exist(targetPath + newFileName)) {
File file = FileUtil.newFile(targetPath + newFileName);
List<Object> lineList = new ArrayList<>();
lineList.add("<mapper namespace=\"" + packageName + newFileName.replace(".xml", "") + "\">");
lineList.add("");
lineList.add("</mapper>");
FileUtil.writeLines(lineList, file, Charset.defaultCharset());
}
}
}
}

@ -4,13 +4,13 @@ import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
*
* @TableName vp_process
@ -46,6 +46,9 @@ public class Process implements Serializable {
@ApiModelProperty("用户ID")
private String userId;
@ApiModelProperty("图谱关联的ID")
private String graphId;
/**
* :
*

@ -9,6 +9,7 @@
<result property="patientId" column="patient_id" jdbcType="VARCHAR"/>
<result property="medicalRecId" column="medical_rec_id" jdbcType="VARCHAR"/>
<result property="userId" column="user_id" jdbcType="VARCHAR"/>
<result property="graphId" column="graph_id" jdbcType="VARCHAR"/>
<result property="processNo" column="process_no" jdbcType="VARCHAR"/>
<result property="status" column="status" jdbcType="INTEGER"/>
<result property="processType" column="process_type" jdbcType="INTEGER"/>
@ -21,7 +22,7 @@
<sql id="Base_Column_List">
id
,process_no,patient_id,user_id,status,process_type,finish_ask_time,
,process_no,patient_id,user_id,status,process_type,finish_ask_time,graph_id,
create_user_id,create_time,update_user_id,update_time
</sql>

@ -109,4 +109,8 @@ alter table vp_medical_rec
-- 添加素材说明
alter table vp_material_library
add material_desc varchar(512) null comment '素材说明' after directory_id;
add material_desc varchar(512) null comment '素材说明' after directory_id;
-- 添加流程关联的字段
alter table vp_process
add graph_id varchar(64) null comment '图谱ID' after disease_id;
Loading…
Cancel
Save