springboot + neo4j 知识图谱开发

一 、开发背景

最近公司里面要做知识图谱功能,需要后端支持一些查询操作,所以写了一个基本的例子。我自己对于知识图谱的理解也加深了很多。因为我是从零开始的,就是奔着出功能去的,所以可能有些操作会有过时了,或者实现不是很好的等问题,望担待。

二、一些基础知识

知识图谱相关:

什么是知识图谱?

知识图谱(Knowledge Graph)之综述理解

主要是了解知识图谱是个啥玩意,包括哪几部分等

cypher基本语法(neo4j数据库使用的,类似于mysql数据库使用的是sql语法。。。大概这样)

Neo4j常用的查询

查询子节点和关系

基本语法

三、代码编写

1.pom.xml文件

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

        <dependency>
            <groupId>org.neo4j</groupId>
            <artifactId>neo4j-ogm-http-driver</artifactId>
            <version>3.2.11</version>
        </dependency>

这里需要注意如果只是用了 spring-boot-starter-data-neo4j 的话,连接驱动默认使用的是bolt协议。bolt协议好像底层使用二进制操作,更高效。如果要是用http协议的话要加入neo4j-ogm-http-driver 。版本要和neo4j一样,在依赖里面查下。

2.配置文件

spring:
  data:
    neo4j:
      uri: bolt://127.0.0.1:7687
      username: neo4j
      password: 1234

使用bolt协议,端口使用7687,使用http协议,端口使用7474,这些是默认端口。这个端口可以在neo4j配置,如果配置了就去查下对应的端口。

3.关系节点

/**
 * 关系节点
 */
@NodeEntity(label = "Element")
public class SupplyGraph {
    private long id;

    private String desc;
    @Id
    private String eleId;

    private String eleName;


    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public String getEleId() {
        return eleId;
    }

    public void setEleId(String eleId) {
        this.eleId = eleId;
    }

    public String getEleName() {
        return eleName;
    }

    public void setEleName(String eleName) {
        this.eleName = eleName;
    }
}

@NodeEntity 指定当前类为节点类,label需要和neo4j中的Node label中的对应。

4. repository编写

public interface SupplyRepository  extends Neo4jRepository<SupplyGraph,Long> {

    SupplyGraph findByEleName(String name);


    @Query("Match (p:Element)-[*]->(s:Element) where p.eleId = {eleId} return s ")
    List<SupplyGraph> findAllByEleId(@Param("eleId") String eleId);

}

repository可以继承Neo4jRepository 按照jpa的方式编写或者实现自定义的查询。查询语句中的实体名称(Element)需要和neo4j中的一样,不能放自己定义的实体类名称(SupplyGraph)。

5.编写controller访问

 

    @Autowired
    private SupplyRepository supplyRepository;
    
    @GetMapping("/hello")
    private WebResult hello() {
        WebResult r = new WebResult();
        List<SupplyGraph> allByEleId = supplyRepository.findAllByEleId("5");
        r.setData(allByEleId);
        return r;
    }

6,查询节点和节点间的关系

使用session的方式来查询。

先将session配置进去,配置类如下:

@Configuration
public class Neo4jSourceConfig {

    @Value("${spring.data.neo4j.uri}")
    private String url;

    @Value("${spring.data.neo4j.username}")
    private String username;

    @Value("${spring.data.neo4j.password}")
    private String password;

    @Bean(name = "session")
    public Session neo4jSession() {
        Driver driver = GraphDatabase.driver(url, AuthTokens.basic(username, password));
        return driver.session();
    }
}

然后使用session执行查询语句,查询语句中要讲节点和关系返回,那么返回结果里面会包含节点信息和关系信息。

执行查询语句如下:

  @Autowired
    private Session session;
    private void test(){
        if (session.isOpen()) {
            String cql = String.format("Match (p:Element)-[r]->(s:Element) where p.eleId ='%s' return s,r", supplyGraph.getEleId());
            Result run = session.run(cql);
        }
    }

处理返回结果:

        while (run.hasNext()) {
                Record next = run.next();
                GraphNodeResult nodeResult = new GraphNodeResult(); //节点类
                GraphRelationResult relationResult = new GraphRelationResult(); //关系类
                for (Value value : next.values()) {
                    if (TextUtils.equals(value.type().name(), "RELATIONSHIP")) { //是关系类型的数据
                        Relationship relationship = value.asRelationship();
                        Map<String, Object> map = relationship.asMap(); //返回关系所有属性的map
                        Set<String> keySet = map.keySet();
                        relationResult.setTarget(nodeResult.getName());
                        for (String s : keySet) {
                            if (TextUtils.equals(s, "type")) {
                                relationResult.setName((String) map.get(s));
                                relationResult.setDes((String) map.get(s));
                            }
                        }
                    } else {  //是节点类型的数据NODE
                        Node node = value.asNode();
                        Map<String, Object> map = node.asMap(); //这里是一个节点所有属性的map
                        Set<String> keySet = map.keySet();
                        nodeResult.setCategory(category + 1);
                        for (String s1 : keySet) {
                            if (TextUtils.equals(s1, "eleName")) {
                                nodeResult.setName((String) map.get(s1));
                            } else if (TextUtils.equals(s1, "desc")) {
                                nodeResult.setDes((String) map.get(s1));
                            }
                        }

                    }
                }
           
            }
    
        }

四、碰到的问题

1.Make sure you are not trying to connect to the http endpoint (HTTP defaults to port 7474 whereas BOLT defaults to port 7687)

原因:配置文件中端口和协议不对应,我使用的是bolt协议,但是端口是7474

解决办法:修改端口,和协议对应。bolt使用7687端口,http使用7474端口

2.SupplyRepository  自定义的查询不执行

原因:实体类型和neo4j数据库中的类型不对应

解决办法:将语句中的实体类型修改为neo4j中的数据类型,而不是代码中实体的类名。。。。

 

参考资料:

1.什么是知识图谱?

2.知识图谱(Knowledge Graph)之综述理解

3.基本语法

4.常用查询

5.玩转neo4j

 

  • 0
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值