Java 批量导入CSV文件到Neo4j创建知识图谱(附测试数据)

测试类

注意jdk的安装版本,最好使用jdk1.7以上的版本。

package com.clinicalresearch.core.utils.Neo4jUtils;

import com.clinicalresearch.core.utils.Collections.CreateFileUtil;
import com.csvreader.CsvReader;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.sf.json.JSONObject;
import org.neo4j.driver.v1.*;
import org.neo4j.driver.v1.types.Node;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import static org.neo4j.driver.v1.Values.parameters;

/**
 * Created by liangguannan on 2019/12/24.
 */
public class Neo4jSessionTest {

    public final static ObjectMapper mapper = new ObjectMapper();

    public static Session session=null;

    public static Driver driver=null;

    static {
        /**
         * 使用neo4j的session执行条件语句statement,一定要使用这个反序列化对象为json字符串
         * 下面的设置的作用是,比如对象属性字段name="李二明",正常反序列化json为 == "name":"李二明"
         * 如果使用下面的设置后,反序列name就是 == name:"appleyk"
         * 而session执行语句create (:儿子{"name":"李二明","uuid":3330,"age":12,"height":"165cm"})会报错
         * 因此,......etc
         */
        mapper.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);

        driver = GraphDatabase.driver( "bolt://10.10.202.118:7687", AuthTokens.basic( "neo4j", "123456" ) );
        session = driver.session();
    }

    public static void createNodeAndRelation() throws Exception {

        /**
         * 建立一个爸爸与儿子的关系
         */

        // 1.首先创建爸爸节点
        RNode rDad = new RNode();
        rDad.setUuid(1110);
        rDad.setLabel("爸爸");
        // 2.其次为爸爸节点添加属性 == Property Keys
        rDad.addProperty("uuid", 1110);
        rDad.addProperty("name", "李大明");
        rDad.addProperty("age", 45);
        rDad.addProperty("height", "182.5cm");
        // 3.添加关系
        REdge edge = new REdge();
        edge.addProperty("relationID", 521);
        edge.addProperty("time", "1997-05-12");
        edge.setRelationID(521);
        edge.setName("父亲");
        // 4.为关系节点添加指向节点 == 创建儿子节点
        RNode rSon = new RNode();
        rSon.setUuid(2220);
        rSon.setLabel("儿子");
        // 5.为儿子节点添加属性 == Property Keys
        rSon.addProperty("uuid", 2220);
        rSon.addProperty("name", "李小明");
        rSon.addProperty("age", 20);
        rSon.addProperty("height", "185cm");
        // 6.给爸爸节点添加关系
        rDad.setEdge(edge);

        createNode(rDad);
        createNode(rSon);
        createRelation(rDad,rSon);
        System.err.println("创建成功");

    }

    /**
     * 创建节点
     * @param rNode
     * @throws Exception
     */
    public static void createNode(RNode rNode) throws Exception{
        RNode srcNode = queryNode(rNode);
        //查node是否已經存在了,不存在則創建
        if(srcNode == null){
            String propertiesString = mapper.writeValueAsString(rNode.getProperties());
            String cypherSql = String.format("create (:%s%s)", rNode.getLabel(), propertiesString);
            System.out.println(cypherSql);
            session.run(cypherSql);
            System.err.println("创建节点:"+rNode.getLabel()+"成功!");
        }else{
            System.err.println("节点已存在,跳过创建");
        }
    }

    /**
     * 创建关系
     * @param srcNode
     * @param tarNode
     * @throws Exception
     */
    public static void createRelation(RNode srcNode,RNode tarNode) throws Exception{
        REdge edge = queryRelation(srcNode,tarNode);
        if(edge == null){
            edge = srcNode.getEdge();
            String propertiesString = mapper.writeValueAsString(edge.getProperties());
            String cypherSql = String.format("match(a),(b) where a.uuid=%d and b.uuid=%d create (a)-[r:%s %s]->(b)",
                    srcNode.getUuid(),tarNode.getUuid(),
                    edge.getName(), propertiesString);
            System.out.println(cypherSql);
            session.run(cypherSql);
            System.err.println("创建关系:"+edge.getName()+"成功!");
        }else{
            System.err.println("关系已存在,跳过创建");
        }
    }


    /**
     * 查询节点
     *
     * @param rNode
     * @return
     */
    public static RNode queryNode(RNode rNode) {
        RNode node = null;
        REdge redge=rNode.getEdge();

        String cypherSql = String.format("match(n:%s) where n.%s = %d return n",redge.getLabel(), redge.getNodeIdName(), rNode.getUuid());
        StatementResult result = session.run(cypherSql);
        if (result.hasNext()) {
            Record record = result.next();
            for (Value value : record.values()) {
                /**
                 * 结果里面只要类型为节点的值
                 */
                if (value.type().name().equals("NODE")) {
                    Node noe4jNode = value.asNode();
                    node = new RNode();
                    node.setLabel(rNode.getLabel());
                    node.setProperties(noe4jNode.asMap());

                }
            }
        }
        return node;
    }


    /**
     * 查询关系
     * @param srcNode
     * @param tarNode
     * @return
     */
    public static REdge queryRelation(RNode srcNode,RNode tarNode){
        REdge edge = srcNode.getEdge();
        String cypherSql =String.format("match(n)-[r:%s]-(b) where n.%s = %d and b.%s = %d return r",
                edge.getName(),srcNode.getNodeIdName(),srcNode.getUuid(),srcNode.getNodeIdName(),tarNode.getUuid());
        StatementResult result = session.run(cypherSql);
        if(result.hasNext()){
            return edge;
        }
        return null;
    }

    /**
     * 读取CSV文件
     * @param diseaseName
     * @param filePath :全路径名
     * @param type
     * @param nodeIdName
     */
    public static List<String[]> readCSV(String diseaseName, String filePath, String type, String nodeIdName) throws Exception {
        CsvReader reader = null;
        List<String[]> dataList = new ArrayList<String[]>();

        char separator = ',';

        try {
            //如果生产文件乱码,windows下用gbk,linux用UTF-8
            reader = new CsvReader(filePath, separator, Charset.forName("UTF-8"));

            // 读取表头
            reader.readHeaders();
            String[] headArray = reader.getHeaders();//获取标题
            System.out.println(headArray[0] +"  " + headArray[1] + " " + headArray[2]);

            // 逐条读取记录,直至读完
            while (reader.readRecord()) {
                // 读一整行
                System.out.println("读一整行 "+reader.getRawRecord());
                // 读这行的第一列
                System.out.println("读这行的第一列: "+reader.get(0));//id
                // 读这行的第二列
                System.out.println("读这行的第二列: "+reader.get(1));//title

                System.out.println("读这行的第三列: "+reader.get(2));//level

                if ("Node".equals(type)){
                    createNodeTest(diseaseName,Integer.valueOf(reader.get(0)),reader.get(1),reader.get(2),reader.get(3),nodeIdName);
                }else {
                    createRelationTest(reader.get(2),Integer.valueOf(reader.get(0)),Integer.valueOf(reader.get(1)),nodeIdName);
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != reader) {
                reader.close();
            }
        }

        return dataList;
    }

    /**
     * 数据 创建节点
     * @param diseaseName
     * @param srcNodeUuid
     * @param title
     * @param level
     * @param describe
     * @param nodeIdName
     * @throws Exception
     */
    public static void createNodeTest(String diseaseName, int srcNodeUuid, String title, String level, String describe, String nodeIdName) throws Exception{
        REdge edge1 = new REdge();
        edge1.setLabel(diseaseName);
        edge1.setTitle(title);
        edge1.setNodeIdName(nodeIdName);

        RNode rNode= new RNode();
        rNode.setUuid(srcNodeUuid);
        rNode.setEdge(edge1);

        RNode srcNode = queryNode(rNode);
        //查node是否已經存在了,不存在則創建
        if(srcNode == null){
            String cypherSql =String.format("CREATE (n:%s {%s: {%s}, title: {title}, level: {level}, describe: {describe}})",
                    diseaseName,nodeIdName,nodeIdName);//一个总的根节点

            session.run(cypherSql,
                    parameters( nodeIdName, srcNodeUuid, "title", title,"level", level,"describe",describe) );

            System.err.println("创建节点:"+edge1.getLabel()+"成功!");
        }else{
            System.err.println("节点已存在,跳过创建");
        }
    }

    /**
     * excel 数据 创建节点关系
     * @param srcNodeUuid
     * @param tarNodeUuid
     * @param nodeIdName
     * @throws Exception
     */
    public static void createRelationTest(String name, int srcNodeUuid, int tarNodeUuid, String nodeIdName) throws Exception{
        REdge edge1 = new REdge();
        edge1.setName(name);

        RNode srcNode= new RNode();
        srcNode.setUuid(srcNodeUuid);
        srcNode.setEdge(edge1);
        srcNode.setNodeIdName(nodeIdName);

        RNode tarNode= new RNode();
        tarNode.setUuid(tarNodeUuid);

        REdge edge = queryRelation(srcNode,tarNode);
        if(edge == null){
            edge = srcNode.getEdge();
            String propertiesString = mapper.writeValueAsString(edge.getProperties());
            String cypherSql = String.format("match(a),(b) where a.%s=%d and b.%s=%d create (a)-[r:%s %s]->(b)",
                    nodeIdName,srcNode.getUuid(),nodeIdName,tarNode.getUuid(),
                    edge.getName(), propertiesString);
            System.out.println(cypherSql);
            session.run(cypherSql);
            System.err.println("创建关系:"+edge.getName()+"成功!");
        }else{
            System.err.println("关系已存在,跳过创建");
        }
    }

    /**
     * 知识图谱 节点数据
     * @throws Exception
     * @param diseaseName
     */
    public static void createNodeByFile(String diseaseName) throws Exception{

        String type="Node";

        List<JSONObject> list=CreateFileUtil.readfile("C:\\Users\\liangguannan\\Desktop\\neo4j数据\\脑梗塞\\node");

        for (int i=0;i<list.size();i++){
            JSONObject jsonObject=list.get(i);

            String filePath=jsonObject.get("path").toString();

            String nodeIdName=diseaseName+"_nodeId";

            readCSV(diseaseName,filePath,type,nodeIdName);
        }
    }

    /**
     * 知识图谱 关系数据
     * @throws Exception
     * @param diseaseName
     */
    public static void createRelationByFile(String diseaseName) throws Exception{

        String type="Relation";

        List<JSONObject> list=CreateFileUtil.readfile("C:\\Users\\liangguannan\\Desktop\\neo4j数据\\脑梗塞\\relation");


        for (int i=0;i<list.size();i++){

            JSONObject jsonObject=list.get(i);

            String filePath=jsonObject.get("path").toString();

            String nodeId=diseaseName+"_nodeId";
            String name=null;

            readCSV(name,filePath,type,nodeId);
        }

    }

    public static void main(String[] args) {
        try {

            //createNodeAndRelation();

            String name="cerebralInfarction";

            createNodeByFile(name);//读取文件夹下的节点excel集合
            createRelationByFile(name);//读取文件夹下关系excel集合


            //createRelationTest(50001,7);

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            session.close();
            driver.close();
        }
    }
}

RNode 类

package com.clinicalresearch.core.utils.Neo4jUtils;


/**
 * Created by  on 2019/12/24.
 */
public class RNode extends RObject {

    /**
     * 节点的uuid == 对应其他数据库中的主键
     */
    private int uuid;

    /**
     * 节点里面是否包含有边 == 关系
     */
    private REdge edge;

    public Integer getUuid() {
        return uuid;
    }

    public void setUuid(Integer uuid) {
        this.uuid = uuid;
    }

    public REdge getEdge() {
        return edge;
    }

    public void setEdge(REdge edge) {
        this.edge = edge;
    }
}

REdge类

package com.clinicalresearch.core.utils.Neo4jUtils;

/**
 * 边 == 关系
 * Created by liangguannan on 2019/12/24.
 */
public class REdge extends RObject {

    /**
     * 关系的ID  ==  聚合、连接、属于、包括等,这些关系可能是枚举字典,因此记录关系ID是有必要的
     */
    private int relationID;

    /**
     * 关系名称
     */
    private String name;

    /**
     * 关系指向哪一个节点 == 可能这个节点还有关系【节点关系递增下去】
     */
    private RNode  rNode;

    public Integer getRelationID() {
        return relationID;
    }

    public void setRelationID(Integer relationID) {
        this.relationID = relationID;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public RNode getrNode() {
        return rNode;
    }

    public void setrNode(RNode rNode) {
        this.rNode = rNode;
    }
}

RObject 类

package com.clinicalresearch.core.utils.Neo4jUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * 节点和关系对象的基类,含公共部分的id、标签label以及属性properties
 * Created by liangguannan on 2019/12/24.
 */
public class RObject {
    /**
     * 节点标签名称 == Node Labels
     */
    private String label;

    /**
     * 节点标题
     */
    private String title;

    /**
     * 节点id的名称
     */
    private String nodeIdName;
    /**
     * 节点属性键值对 == Property Keys
     */
    private Map<String, Object> properties;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getNodeIdName() {
        return nodeIdName;
    }

    public void setNodeIdName(String nodeIdName) {
        this.nodeIdName = nodeIdName;
    }

    public RObject(){
        properties = new HashMap<>();
    }


    public String getLabel() {
        return label;
    }
    public void setLabel(String label) {
        this.label = label;
    }
    public Map<String, Object> getProperties() {
        return properties;
    }

    /**
     * 添加属性
     * @param key
     * @param value
     */
    public void addProperty(String key,Object value){
        properties.put(key, value);
    }

    /**
     * 拿到属性
     * @param key
     * @return
     */
    public Object getProperty(String key){
        return properties.get(key);
    }
    /**
     * 移除属性
     * @param key
     */
    public void removeProperty(String key){
        properties.remove(key);
    }

    public void setProperties(Map<String, Object> properties) {
        this.properties = properties;
    }
}

读取Excel文件夹下的所有文件

package com.clinicalresearch.core.utils.Collections;

/**
 * Created by liangguannan on 2018/5/4.
 */
import com.clinicalresearch.core.utils.JsonFormatTool;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.clinicalresearch.utils.HttpClientUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class CreateFileUtil {

    /**
     * 生成.json格式文件
     */
    public static boolean createJsonFile(String jsonString, String filePath, String fileName) {
        // 标记文件生成是否成功
        boolean flag = true;

        // 拼接文件完整路径
        String fullPath = filePath + File.separator + fileName + ".json";

        // 生成json格式文件
        try {
            // 保证创建一个新文件
            File file = new File(fullPath);
            if (!file.getParentFile().exists()) { // 如果父目录不存在,创建父目录
                file.getParentFile().mkdirs();
            }
            if (file.exists()) { // 如果已存在,删除旧文件
                file.delete();
            }
            file.createNewFile();

            // 格式化json字符串
            jsonString = JsonFormatTool.formatJson(jsonString);

            // 将格式化后的字符串写入文件
            Writer write = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
            write.write(jsonString);
            write.flush();
            write.close();
        } catch (Exception e) {
            flag = false;
            e.printStackTrace();
        }

        // 返回是否成功的标记
        return flag;
    }

    /**
     * 通过本地文件访问json并读取
     * @param path:E:/svn/05.Hospital/templatedept_uuid.json
     * @return:json文件的内容
     */
    public static String ReadFile(String path){
        String laststr="";
        File file=new File(path);// 打开文件
        BufferedReader reader=null;
        try{
            FileInputStream in = new FileInputStream(file);
            reader=new BufferedReader(new InputStreamReader(in,"UTF-8"));// 读取文件
            String tempString=null;
            while((tempString=reader.readLine())!=null){
                laststr=laststr+tempString;
            }
            reader.close();
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            if(reader!=null){
                try{
                    reader.close();
                }catch(IOException el){
                }
            }
        }
        return laststr;
    }




    /**
     * 读取某个文件夹下的所有文件
     */
    public static List<JSONObject> readfile(String filepath) throws FileNotFoundException, IOException {
        List<JSONObject> list= new ArrayList();

        try {
            File file = new File(filepath);
            if (!file.isDirectory()) {
                System.out.println("文件");
                System.out.println("path=" + file.getPath());
                System.out.println("absolutepath=" + file.getAbsolutePath());
                System.out.println("name=" + file.getName());

            } else if (file.isDirectory()) {
                System.out.println("文件夹");
                String[] filelist = file.list();
                for (int i = 0; i < filelist.length; i++) {
                    File readfile = new File(filepath + "\\" + filelist[i]);
                    if (!readfile.isDirectory()) {
                        System.out.println("path=" + readfile.getPath()+"========="+readfile.getName());

                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("path",readfile.getPath());
                        jsonObject.put("name",readfile.getName());

                        //getAllItems(readfile.getPath(),readfile.getName());

                        list.add(jsonObject);

                    } else if (readfile.isDirectory()) {
                        readfile(filepath + "\\" + filelist[i]);
                    }
                }

            }

        } catch (FileNotFoundException e) {
            System.out.println("readfile()   Exception:" + e.getMessage());
        }
        return list;
    }



    public static void main(String[] args) {



    }
}

测试数据网盘地址:

https://share.weiyun.com/TfBlKS4t

访问neo4j数据库查看
在这里插入图片描述

评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值