ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

neo4j使用

2021-07-13 12:05:51  阅读:163  来源: 互联网

标签:return name param session template 使用 neo4j public


文章目录

简介

图数据库的基本含义是以“图”这种数据结构存储和查询数据,而不是存储图片的数据库。它的数据模型主要是以节点和关系(边)来体现,也可处理键值对。它的优点是快速解决复杂的关系问题。

数据结构:
在一个图中主要包含两种数据类型:Nodes(节点)和Relationships(关系)。他们各自内部又包含key-value形式的属性,然后节点之间通过关系相连,形成了关系型的网状结构

优点:

  1. 更快的数据库操作。当然,有一个前提条件,那就是数据量较大,在MySql中存储的话需要许多表,并且表之间联系较多(即有不少的操作需要join表)。
  2. 数据更直观,相应的SQL语句也更好写(Neo4j使用Cypher语言,与传统SQL有很大不同)。
  3. 更灵活。不管有什么新的数据需要存储,都是一律的节点和边,只需要考虑节点属性和边属性。而MySql中即意味着新的表,还要考虑和其他表的关系。
  4. 数据库操作的速度并不会随着数据库的增大有明显的降低。这得益于Neo4j特殊的数据存储结构和专门优化的图算法。

基础语法

neo4j的系统操作

:help server 查看系统操作
:server disconnect :退出当前账户
:servcer connect 当前登录信息

简单的 增删改查

  1. 增加数据:

    增加节点

    1. create (a:PersonP{name:“xxx”,age:22})
      在这里插入图片描述

      增加的时候,会自动生成ID,如果在新加的时候想得到ID:

    2. create (a:PersonP{name:“xxx”,age:22}) retrun ID(a)

  2. 增加节点的关系:

    match (p1:Person),(p2:Person) where p1.name=“李四” and p2.name=“张三” create (p1)-[:DD{relation:“弟弟”}]->(p2)
    在这里插入图片描述

  3. 查询数据

​ 1. 查询节点

  1. 查询全部节点

    MATCH (n:Person) RETURN n LIMIT 25 LIMIT:限制只查25个,去掉限制就是查询全部

在这里插入图片描述

  1. 按条件查询

    1. 单条件:

      MATCH (n:Person) where n.name=“李四” RETURN n

      在这里插入图片描述

    2. 多条件:

      MATCH (n:Person) where n.name=“李四” or n.name=“张三” RETURN n

      或者

      MATCH (n:Person{name:“李四”}),(n2:Person{name:“张三”}) RETURN n,n2

      在这里插入图片描述

      1. 查询节点的关系

        1. 查询所有

          MATCH p=()-[r:DD]->() RETURN p LIMIT 25 LIMIT:限制只查25个,去掉限制就是查询全部

        2. 按条件查询

          MATCH (n:Person{name:“王五”})-[r:DD]->(n1:Person{name:“李四”}) RETURN r,n,n1

        3. 多级查询:

          1. 查所有

            MATCH p=()-[r:DD]->()-[r1:DD]->() RETURN p LIMIT 25

          2. 按条件

            MATCH (n1:Person{name:“王五”})-[r1:DD]->(n2:Person{name:“李四”})-[r2:DD]->(n3:Person{name:“张三”}) RETURN r1,r2,n1,n2,n3

在这里插入图片描述

  1. 修改数据

    1. 节点数据修改

      match (n:Person) where n.name=“王五” set n.name=“赵六”

在这里插入图片描述

  1. 修改节点关系

    MAtch (a:Person{name:“赵六”})-[r:DD]->(b:Person{name:“李四”}) create (a)-[r2:AA{relation:“哥哥”}]->(b) set r2=r WITH r delete r

在这里插入图片描述

  1. 删除

    1. 根据ID删除 并且删除其相关的关系

      match ® where id®= 51439 detach delete r

    2. 删除节点的属性

      match (n:Person{name:“张三”}) REMOVE n.age

      在这里插入图片描述

    3. 删除所有

      match (n:Person) delete n

    4. 删除没有关系的节点

      match (n:Person) where n.name=“张三” delete n

    5. 删除所有关系

      match (a)-[r]-(b) delete r

    6. 按条件删除节点间关系

      MAtch (a:Person{name:“李四”})-[r:DD]-(b:Person{name:“张三”}) delete r

JAVA实现

在配置文件中,定义Neo4j的域名、密码等属性

#图库连接地址
neo4j.uri = bolt://192.168.80.108:7687,bolt://192.168.80.109:7687,bolt://192.168.80.110:7687
#图库连接用户名
neo4j.username = neo4j
#图库连接密码
neo4j.password = neo4j
#连接池总连接的最大数
neo4j.maxTotal = 5
#获取连接的最大等待毫秒数
neo4j.maxWaitMillis = 5000

编写config文件,读取配置文件的内容

@Data
@Configuration
@ConfigurationProperties(prefix = "neo4j")
public class Neo4jConfig {

    /**
     * 获取连接最长等待时长
     */
    public static final Long DEFAULT_MAX_WAIT_MILLIS = 5000L;

    public static final Boolean DEFAULT_TEST_ON_BORROW = true;

    /**
     * 多个用逗号分隔
     */
    private String uri;

    private String username;

    private String password;

    private String maxTotal;

    private Boolean testOnBorrow = DEFAULT_TEST_ON_BORROW;

    private Long maxWaitMillis = DEFAULT_MAX_WAIT_MILLIS;
}

因为是集群,所有编写Factory工厂类

@Component
public class Neo4jSessionFactory extends BasePooledObjectFactory<Session> {

    @Autowired
    Neo4jConfig neo4jConfig;

    static Random random = new Random();

    @Override
    public Session create() throws Exception {
        String driverUrl = chooseDriver(neo4jConfig.getUri().split(","));
        return GraphDatabase.driver(driverUrl, AuthTokens.basic(neo4jConfig.getUsername(), neo4jConfig.getPassword())).session();
    }

    @Override
    public PooledObject<Session> wrap(Session session) {
        return new DefaultPooledObject<>(session);
    }

    @Override
    public void destroyObject(PooledObject<Session> p) throws Exception {
        Session session = p.getObject();

        if (session != null) {
            session.close();
        }
    }

    @Override
    public boolean validateObject(PooledObject<Session> p) {
        Session session = p.getObject();
        if (session != null) {
            return session.isOpen();
        } else {
            return false;
        }
    }

    /**
     * 随机负载均衡
     * @param datas
     * @return
     */
    private static String chooseDriver(String[] datas) {
        int length = datas.length;
        int dataIndex = random.nextInt(length);
        return datas[dataIndex];
    }
}

根据自己的业务,创建模板类(节点创建、关系创建)

public class Neo4jConstant {


    /**
     * 创建账号节点
     */
    public static final String ACCOUNT_NODE_TEMPLATE_BY_PIGEONHOLE = "UNWIND {batch} as row \n" +
            "MERGE(accountEntity:AccountEntity{id:row.id}) ON \n" +
            "CREATE SET accountEntity.account=row.account,accountEntity.accountType=row.accountType";


    /**
     * 通联关系创建模板
     */
    public static final String LINK_RELATION_TEMPLATE = "UNWIND {batch} as row \n" +
            " match (n:AccountEntity),(m:AccountEntity) where n.id = row.account1 and m.id = row.`account2` \n" +
            " MERGE (n) -[r:LINKS]->(m) \n" +
            " ON CREATE SET r.relationTimes=row.relationTimes,r.firstRelationTime=row.firstRelationTime,r.lastRelationTime=row.lastRelationTime,r.type=row.type,r.linkType=row.linkType,r.linkFrom=row.linkFrom\n" +
            " ON MATCH SET r.relationTimes=r.relationTimes+row.relationTimes,r.lastRelationTime=row.lastRelationTime\n" +
            " return r";

}

编写neo4j的java具体实现,包含(增删改查,连接,关闭)

一般的查询,都需要自己组装成DSL语句

@Slf4j
@Service
public class Neo4jService {

    @Autowired
    Neo4jSessionFactory neo4jSessionFactory;

    @Autowired
    Neo4jConfig neo4jConfig;

    GenericObjectPool genericObjectPool;

    @PostConstruct
    public void init() {
        GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();

        if (StringUtils.isNotBlank(neo4jConfig.getMaxTotal())) {
            genericObjectPoolConfig.setMaxTotal(Integer.valueOf(neo4jConfig.getMaxTotal()));
            genericObjectPoolConfig.setMinIdle(Integer.valueOf(neo4jConfig.getMaxTotal()));
            genericObjectPoolConfig.setMaxIdle(Integer.valueOf(neo4jConfig.getMaxTotal()));
        }

        genericObjectPoolConfig.setTestOnBorrow(neo4jConfig.getTestOnBorrow());
        genericObjectPoolConfig.setMaxWaitMillis(neo4jConfig.getMaxWaitMillis());
        genericObjectPool = new GenericObjectPool(neo4jSessionFactory, genericObjectPoolConfig);
    }

    /**
     * 禁止使用此方法,会导致资源泄露问题 !!!
     *
     * @return
     */
    public Session createNewSession() {
        try {
            return (Session) genericObjectPool.borrowObject();
        } catch (Exception e) {
            log.error("获取 neo4j 连接出错 {}", e);
        }

        return null;
    }

    /**
     * 使用完会话必须关闭 !!!
     *
     * @param session
     */
    public void closeSession(Session session) {
        try {
            if (session != null) {
                genericObjectPool.returnObject(session);
            }
        } catch (Exception e) {
            log.error("归还连接出错 {}", e);
        }
    }

    /**
     * 批量执行 dsl
     *
     * @param template
     * @param params
     */
    public void executeBatch(String template, JSONArray params) {
        Session session = null;

        try {
            if (params != null && params.size() > 0) {
                session = createNewSession();

                JSONObject batch = new JSONObject();
                batch.put("batch", params);
                log.info("开始执行批插入 模板:{} 参数: {} ", template, params);
                session.run(template, batch);
            }
        } catch (Exception e) {
            log.error("executeBatch error:{}", e);
        } finally {
            closeSession(session);
        }
    }

    public void executeBatch(Session session, String template, JSONArray params) {
        try {
            if (params != null && !params.isEmpty()) {
                JSONObject batch = new JSONObject();
                batch.put("batch", params);
                log.info("开始执行批插入 模板:{} 参数: {} ", template, params);
                session.run(template, batch);
            }
        } catch (Exception e) {
            log.error("executeBatch error:{}, error msg:{}", e, e.getMessage());
        }
    }

    /**
     * 单条查询
     *
     * @param template
     * @param param
     * @return
     */
    public List<Record> queryBatch(String template, Map<String, Object> param) {
        List<Record> records = new ArrayList<>();
        Session session = null;

        try {
            if (param != null && param.size() > 0) {
                session = createNewSession();

                JSONObject batch = new JSONObject();
                batch.put("batch", param);
                log.debug("开始执行批插入 模板:{} 参数: {} ", template, param);
                StatementResult result = session.run(template, batch);
                records = extractRecordsFromResult(result);
                return records;
            }
        } finally {
            closeSession(session);
        }

        return records;
    }


    /**
     * 执行单条
     *
     * @param template
     * @param param
     */
    public void execute(String template, Map<String, Object> param) {
        Session newSession = null;

        try {
            if (param != null && param.size() > 0) {
                newSession = createNewSession();
                newSession.run(template, param);
            }
        } finally {
            closeSession(newSession);
        }
    }

    /**
     * 查询
     *
     * @param template
     * @param param
     * @return
     */
    public List<Record> query(String template, Map<String, Object> param) {
        Session newSession = null;

        try {
            newSession = createNewSession();
            StatementResult result = newSession.run(template, param);
            return extractRecordsFromResult(result);
        } finally {
            closeSession(newSession);
        }
    }

    /**
     * 查询单条结果
     *
     * @param template
     * @param param
     * @return
     */
    public Record queryOne(String template, Map<String, Object> param) {
        Session newSession = null;

        try {
            newSession = createNewSession();
            StatementResult result = newSession.run(template, param);
            return extractOneRecordsFromResult(result);
        } finally {
            closeSession(newSession);
        }
    }

    public Record queryOne(String dsl) {
        Session newSession = null;

        try {
            newSession = createNewSession();
            StatementResult result = newSession.run(dsl);
            return extractOneRecordsFromResult(result);
        } finally {
            closeSession(newSession);
        }
    }

    /**
     * 执行单条
     *
     * @param dsl
     * @return
     */
    public List<Record> queryByDsl(String dsl) {
        Session newSession = null;
        try {
            newSession = createNewSession();
            StatementResult result = newSession.run(dsl);
            return extractRecordsFromResult(result);
        } finally {
            closeSession(newSession);
        }
    }

    /**
     * 抽取 record 中的指定 key
     *
     * @param record
     * @param key
     * @return
     */
    public Map<String, Object> extractRecordToMap(Record record, String key) {
        if (record != null) {
            return record.get(key).asEntity().asMap();
        }

        return null;
    }

    public String extractRecordToString(Record record, String key) {
        if (record != null) {
            return record.get(key).asString();
        }

        return null;
    }

    /**
     * 从 statementResult 中 抽取 Record
     *
     * @param statementResult
     * @return
     */
    public List<Record> extractRecordsFromResult(StatementResult statementResult) {
        ArrayList<Record> records = new ArrayList<>();

        while (statementResult.hasNext()) {
            Record record = statementResult.next();
            records.add(record);
        }

        return records;
    }

    /**
     * 抽取单条记录
     *
     * @param statementResult
     * @return
     */
    public Record extractOneRecordsFromResult(StatementResult statementResult) {
        if (statementResult.hasNext()) {
            return statementResult.next();
        }

        return null;
    }
}

创建结点、关联关系 调用接口

#获取连接
Session session = neo4jService.createNewSession();
#执行模板操作  nodeParams:结点数据,根据自己业务而定。  创建结点
neo4jService.executeBatch(session, Neo4jConstant.ACCOUNT_NODE_TEMPLATE_BY_PIGEONHOLE, nodeParams);
#执行模板操作  nodeRelationParams:关联关系数据,根据自己业务而定。  创建结点之间的关联关系
neo4jService.executeBatch(session, Neo4jConstant.LINK_RELATION_TEMPLATE, nodeRelationParams);

标签:return,name,param,session,template,使用,neo4j,public
来源: https://blog.csdn.net/haobo__/article/details/118696247

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有