【走在生信的路上-2】关系图谱neo4j部署及Springboot集成

前言

最近项目中需要使用关系图谱于是就想到了强大的neo4j是专门用来处理图数据的,所以就给安排上了,同时需要集成Springboot提供接口给前端调用,用来展示数据的关系,并支持可以下钻的方式。

1. neo4j介绍

neo4j是基于java实现的图形数据库,可以存储大量的图信息。可以支持下钻的方式查看数据之间的关系,并可以很好和springboot进行集成,供我们展示数据的关系

2. neo4j 安装

2.1 准备工作

需要安装环境jdk环境,请自行安装
注意neo4j 4.X 版本需要jdk11,neo4j 3.X版本需要jdk8
在官网下载neo4j的安装包官网地址:https://neo4j.com/download-center/
在这里插入图片描述

2.2 安装

将下载好的安装包放入linux下面的目录,因为是jdk8所以我下载的是3.5.25的稳定版本
在这里插入图片描述

进入conf目录下面,用vi编辑器编辑配置文件neo4j.conf
修改的配置信息如下:

  • 修改第22行load csv时l路径,在前面加个#,可从任意路径读取文件
    #dbms.directories.import=import

  • 修改35行和36行,设置JVM初始堆内存和JVM最大堆内存

  • 生产环境给的JVM最大堆内存越大越好,但是要小于机器的物理内存
    dbms.memory.heap.initial_size=5g
    dbms.memory.heap.max_size=10g

  • 修改46行,可以认为这个是缓存,如果机器配置高,这个越大越好
    dbms.memory.pagecache.size=10g

  • 修改54行,去掉改行的#,可以远程通过ip访问neo4j数据库
    dbms.connectors.default_listen_address=0.0.0.0

  • 默认 bolt端口是7687,http端口是7474,https关口是7473,不修改下面3项也可以

  • 修改71行,去掉#,设置http端口为7687,端口可以自定义,只要不和其他端口冲突就行
    #dbms.connector.bolt.listen_address=:7687

  • 修改75行,去掉#,设置http端口为7474,端口可以自定义,只要不和其他端口冲突就行
    dbms.connector.http.listen_address=:7474

  • 修改79行,去掉#,设置http端口为7473,端口可以自定义,只要不和其他端口冲突就行
    dbms.connector.https.listen_address=:7473

  • 修改227行,去掉#,允许从远程url来load csv
    dbms.security.allow_csv_import_from_file_urls=true

  • 修改246行,允许使用neo4j-shell,类似于mysql 命令行之类的
    dbms.shell.enabled=true

  • 修改235行,去掉#,设置连接neo4j-shell的端口,一般都是localhost或者127.0.0.1,这样安全,其他地址的话,一般使用https就行
    dbms.shell.host=127.0.0.1

  • 修改250行,去掉#,设置neo4j-shell端口,端口可以自定义,只要不和其他端口冲突就行
    dbms.shell.port=1337

  • 修改254行,设置neo4j可读可写
    dbms.read_only=false

2.3 启动

使用命令 ./bin/neo4j start启动neo4j
启动成功后浏览器访问 http://服务器ip地址:7474
首次登录账号neo4j,默认密码:neo4j,第一次登录成功后会提示需要修改密码
在这里插入图片描述

2.4 停止

使用命令 ./bin/neo4j stop停止neo4j

2.5 查看状态

使用命令 ./bin/neo4j status查看neo4j的状态
在这里插入图片描述

2.6 导入数据

1)首先把处理好的文件放到到neo4j下面的import目录下面
2)导入前要确认数据实例是否已经存在,比如导入到test
查看neo4j下面的data/databases目录里面是否有test文件夹了,如果有需要手动先删除掉
3) 导入数据
注意如果neo4j在运行,需要先停止掉才能导入数据, 使用命令
./bin/neo4j-admin import --database=test --delimiter="|" --nodes=import/nodes.csv --relationships=import/ed.csv
4) 导入成功后,修改默认的数据库实例为test,再启动neo4j
在这里插入图片描述

浏览器访问就可以在neo4j服务上面看到图数据了
在这里插入图片描述

3. 与Springboot集成

3.1 导入依赖

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-data-neo4j</artifactId>
		<version>2.3.12.RELEASE</version>
	</dependency>

3.2 配置yml文件

neo4j:
uri: bolt://127.0.0.1:7687
username: neo4j
password: xxxxx

3.3 编写配置类

@Configuration
@EnableNeo4jRepositories(basePackages = "org.xxx.neo4j",
        sessionFactoryRef = "neo4jSessionFactory",
        transactionManagerRef = "neo4jTransaction")
public class Neo4jConfig {
    @Value("${neo4j.uri}")
    private String uri;
    @Value("${neo4j.username}")
    private String userName;
    @Value("${neo4j.password}")
    private String password;

    @Bean(name = "neo4jConfiguration")
    public org.neo4j.ogm.config.Configuration neo4jConfiguration() {
        org.neo4j.ogm.config.Configuration configuration = new org.neo4j.ogm.config.Configuration.Builder().uri(uri).connectionPoolSize(100).credentials(userName, password).build();
        return configuration;
    }

    @Bean(name = "neo4jSessionFactory")
    public SessionFactory neo4jSessionFactory() {
        return new SessionFactory(neo4jConfiguration(), "org.xxx.neo4j");
    }

    @Bean(name = "neo4jTransaction")
    public Neo4jTransactionManager neo4jTransaction() {
        return new Neo4jTransactionManager(neo4jSessionFactory());
    }
}

3.4 编写Service

@Service
public class NeoServiceImpl implements INeoService {
    @Resource(name = "neo4jSessionFactory")
    private SessionFactory sessionFactory;


    @Override
    public Map<String, Object> getNodeByName(String nodeName, String nodeLabel) {
        Session session = sessionFactory.openSession();
        //String sql = "MATCH resdata=(n:`" + nodeLabel + "`{node_name:'" + nodeName + "'})-[m]-(q) RETURN resdata limit 10";
        String sql = "MATCH (n:`" + nodeLabel + "`{node_name:'" + nodeName + "'}) return n, (n)-[]-() as resData";
        Result result = session.query(sql, Maps.newHashMap());
        Map<String, Object> resultMap = getListResultNew(result);
        return resultMap;
    }

    private Map<String, Object> getListResultNew(Result result) {
        Map<String, Object> resultMap = new HashMap<>();
        NodeEntity centerNode = null;
        List<NodeResult> nodeResultList = null;
        List<InternalPath.SelfContainedSegment> resData = null;
        Iterable<Map<String, Object>> maps = result.queryResults();
        Iterator<Map<String, Object>> iterator = maps.iterator();
        while (iterator.hasNext()) {
            Map<String, Object> map = iterator.next();
            // 获取中心节点
            NodeModel root = (NodeModel) map.get("n");
            //获取数据节点
            Object obj = map.get("resData");
            if (obj != null) {
                resData = new ArrayList<InternalPath.SelfContainedSegment>();
                InternalPath.SelfContainedSegment[][] internalData = (InternalPath.SelfContainedSegment[][]) map.get("resData");
                int index = internalData.length;
                for (int i = 0; i < index; i++) {
                    InternalPath.SelfContainedSegment one = internalData[i][0];
                    resData.add(one);
                }
            }

            if (root != null) {
                // 根节点
                centerNode = new NodeEntity();
                centerNode.setId(root.getId());
                // Map<String,Object> properties = new HashMap<>();
                Map<String, Object> propertyMap = new HashMap<>();
                // 遍历 propertityList 数组,将 键值对放入 map中
                for (Property<String, Object> property : root.getPropertyList()) {
                    String key = property.getKey();
                    Object value = property.getValue();
                    propertyMap.put(key, value);
                }
                // properties.put("name",root.getPropertyList().get(0).getValue());
                centerNode.setProperties(propertyMap);
                centerNode.setLabels(root.getLabels());
            }

            if (CollectionUtils.isNotEmpty(resData)) {
                nodeResultList = new ArrayList<>();
                for (InternalPath.SelfContainedSegment internalPath : resData) {
                    //处理start
                    Node startNode = internalPath.start();
                    NodeEntity startEntity = new NodeEntity();
                    startEntity.setId(startNode.id());

                    List<String> labelStartList = new ArrayList<>();
                    startNode.labels().forEach(label -> {
                        labelStartList.add(label);
                    });
                    String[] labels = labelStartList.toArray(new String[labelStartList.size()]);
                    startEntity.setLabels(labels);
                    startEntity.setProperties(startNode.asMap());

                    //处理end
                    Node endNode = internalPath.end();
                    NodeEntity endEntity = new NodeEntity();
                    endEntity.setId(endNode.id());
                    List<String> labelEndList = new ArrayList<>();
                    endNode.labels().forEach(label -> {
                        labelEndList.add(label);
                    });
                    String[] labelsEnd = labelEndList.toArray(new String[labelEndList.size()]);
                    endEntity.setLabels(labelsEnd);
                    endEntity.setProperties(endNode.asMap());

                    //处理relationship
                    RelationRef relationRef = new RelationRef();
                    relationRef.setStart(internalPath.relationship().startNodeId());
                    relationRef.setEnd(internalPath.relationship().endNodeId());
                    relationRef.setId(internalPath.relationship().id());
                    relationRef.setType(internalPath.relationship().type());

                    NodeResult nodeResult = new NodeResult();
                    nodeResult.setStart(startEntity);
                    nodeResult.setEnd(endEntity);
                    nodeResult.setRelationship(relationRef);
                    nodeResultList.add(nodeResult);
                }
            }
            // 存放中心节点
            resultMap.put("centerNode", centerNode);
            // 存放关系节点集合
            resultMap.put("relationshipNodeList", nodeResultList);
        }
        return resultMap;
}

3.5 前端展示

前端的展示推荐使用echarts来绘制展示就可以了
最后开发完成效果如下:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学海一叶舟

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值