기반 neo4j지도 데이터베이스, 인구 및 큰 그림의 구현 사이의 관계의 기본 아이디어를 달성했다.

 

때문에 최근의 작업 요구 사항, 저장 및 검색 솔루션 인구 사이의 관계의 큰 그림을 할 필요가, 우리의 주요 데이터 객체는 다음과 같습니다 : 인구 통계 (연령, 신분 카드 번호, 성별 ..), 학교 정보 (학교 주소, 학교 명, 학교 수준, 낮은 등급의 클래스 학교 ..), 고용 정보 (회사 명, 회사 주소, 회사의 기업 신용 코드 ..)뿐만 아니라 논문 게시 된 정보를 찾는 (종이 주제, 참가자, 출판)

질문을 생각 :

  1. 이 인구의 큰 그림, 또는 전화 프로파일 사이의 관계에 대한 데이터는 일반적으로 비 관계형이며, 어떻게 아마도 두 사람 학생, 동료, 동료, 배우자, 남편과 아내, 기타와 같은 조 스미스 홍길동 같은 종 관계의 존재, 그것은 일반적으로 관계형 데이터베이스 (오라클)를 촬영하는 경우 관계의 종류, 예를 들어, 직원 정보 테이블, 학생 테이블, 테이블 동료, 동료 관계형 테이블, 테이블 배우자, 남편과 아내의 관계 테이블을 작성해야합니다 그래서 만약 관계의 후속 증가 그것은 테이블, 테이블 증가를 증가시키고, 후속 데이터베이스를하는 것이 필요하다하는 것은 기본적으로 관계형 테이블, 지속적인 유지 보수, 확장 및 코드 어려운 기계의 수정이며, 단순히 악몽이다.
  2. 위의 첫 번째 시점에서, 우리는 저장소에 관계형 데이터베이스의 사용이 최선의 해결책이 아니라 볼 수 있습니다, 그래서 관계형 데이터 재고의 사용을 생각하기 쉽습니다 후 더 인기있는 비 관계형 데이터베이스에있는 MODY, 레디 스, MongoDB를이 neo4j 필리핀 관계는 하나의 데이터 유형을 저장할 수 있지만, 그들은 여전히 ​​세 개의 서로 다른, 데이터 캐시 컨테이너로 프로젝트의 두 전직 장군, 일부 데이터는 자주 컨테이너에 배치 변경되지 않습니다가, 사람은 자기가 만든이 필요합니다. neoj4j 전용 스토리지 네트워크 다이어그램, 네트워크 다이어그램, 이러한 요구는 우리의 프로젝트 일치하지입니까? 그래서 내 마음은 비밀리에 당신은, neo4j을 것이다 마무리.

데이터베이스 설계 :

 

연관은 테이블에 저장된 ID에 의해 수행되고, 관심있는 사람과 관련된 모든 정보를 제공하여야한다 다섯 추상 객체, 즉 오 그래프 형태로 분할되는 경우. 우리가 명확하게 볼 수있는 그래프에 의해 여러 가지 관계가있다 : - 공부 - 사람들> 학교;

사람 - 출판 논문 -> 종이, 사람들이 - 취임식 -> 기업, 사람 - 생활 -> 홈, 반면에 (한 사람에 대한 참조 노드로) 대외 관계의 이러한 네 가지 범주, 사람들의 스터드 사이의 관계도 있습니다 학생들이 음식으로 간주하므로, 단지 시작에 언급 동료로, 클래스의 학생들이,이 유형의 내부 관계는 우리가 일반적으로 조 스미스와 신원 미상 같은 클래스의 유일한 학교와 같은 외부 관계를 구별 할 필요가 내부 관계,이다, 취임 동료들과 만 회사는 그것을 거의 없습니다 .. 이 경우, 우리는 특히 대외 관계 내부 관계, 논리 정렬을 데이터베이스를 설계했습니다.

구현 :

내 프로젝트는 봄 + springMvc 환경을 사용합니다.

구성 요소 코드 :

나는 한 조각, 다른 패키지의 다른 논리 연산에 구성 및 단체를 neo4j 않습니다.

코드의 일부 :

구성은 neo4j을 설정하는 속성
package com.audaque.module.graphData.neo4j.config;

import org.neo4j.ogm.session.Session;
import org.neo4j.ogm.session.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.*;
import org.springframework.data.neo4j.config.Neo4jConfiguration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/***
 *@ClassName AppConfiguration
 *@desc TODO
 *@Author xxxxxx
 *@Date 2019/5/17 0017 下午 10:57
 *@version 1.0.1
 **/
@Configuration
@EnableNeo4jRepositories(basePackages = "com.audaque.module.graphData.neo4j.repos")
@EnableTransactionManagement
@ComponentScan("com.audaque.module.graphData.neo4j.config")
public class AppConfiguration extends Neo4jConfiguration {
@Autowired private org.neo4j.ogm.config.Configuration config; @Bean public org.neo4j.ogm.config.Configuration getConfiguration() { return config; } @Override @Bean public SessionFactory getSessionFactory() { // with domain entity base package(s) return new SessionFactory(config,"com.audaque.module.graphData.neo4j.model"); } @Override @Bean @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS) public Session getSession() throws Exception { return super.getSession(); } }

  

动态设置属性到Configuration中属性到中
package com.audaque.module.graphData.neo4j.config;

import org.neo4j.ogm.authentication.UsernamePasswordCredentials;
import org.neo4j.ogm.config.Configuration;

import static org.neo4j.ogm.config.DriverConfiguration.CREDENTIALS;
import static org.neo4j.ogm.config.DriverConfiguration.DRIVER;
import static org.neo4j.ogm.config.DriverConfiguration.URI;

/***
 *@ClassName MyConfiguration
 *@desc 自定义bean动态配置neo4j数据源。
 *@Author [email protected]
 *@Date 2019/5/24 9:14
 *@version 1.0.1
 **/
public class MyConfiguration extends Configuration {
    public MyConfiguration(String driverClass,String driverURL,String userName,String password){
        super.set(DRIVER[0],driverClass);
        super.set(URI[0],driverURL);
        super.set(CREDENTIALS[0],new UsernamePasswordCredentials(userName, password));

    }

}


PaperInfoRepository配置(实体的保存):
package com.audaque.module.graphData.neo4j.repos;

import com.audaque.module.graphData.neo4j.model.PaperInfo;
import org.springframework.data.neo4j.repository.GraphRepository;
import org.springframework.stereotype.Repository;

/***
 *@ClassName PaperInfoRepository
 *@desc 论文信息接口
 *@Author xxxx
 *@Date 2019/5/17 0017 下午 5:43
 *@version 1.0.1
 **/
@Repository
public interface PaperInfoRepository extends GraphRepository<PaperInfo> {



}

 

内部关系的Repository我采用的自定义查询语句查询,如下:

package com.audaque.module.graphData.neo4j.repos;

import com.audaque.module.graphData.neo4j.model.Neo4jRelationInfo;
import org.neo4j.consistency.store.paging.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.GraphRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/***
 *@ClassName Neo4jRelationInfoRepository
 *@desc 八大关系型数据。
 *@Author xxxx
 *@Date 2019/5/17 0017 下午 5:43
 *@version 1.0.1
 **/
@Repository
public interface Neo4jRelationInfoRepository extends GraphRepository<Neo4jRelationInfo> {

    /**
     *  pe - pe 邻居关系
     * @param fromId
     * @param toId
     * @return
     */
    @Query(value = "match(a:pe),(b:pe) where a.ids={fromId} and b.ids={toId}  merge (a) - [r:邻居{direction:{direction}}]->(b)")
    Neo4jRelationInfo generateGraphDataRelation_LJ(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction);

    /**
     *  pe -> pe 同学关系
     * @param fromId
     * @param toId
     * @return
     */
    @Query(value = "match(a:pe),(b:pe) where a.ids={fromId} and b.ids={toId}  merge (a) - [r:同学{direction:{direction}}]->(b)")
    Neo4jRelationInfo generateGraphDataRelation_TX(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction);

    /**
     *  pe -> pe 校友关系
     * @param fromId
     * @param toId
     * @return
     */
    @Query(value = "match(a:pe),(b:pe) where a.ids={fromId} and b.ids={toId}  merge (a) <- [r:校友{direction:{direction}}]->(b)")
    Neo4jRelationInfo generateGraphDataRelation_XY(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction);

    /**
     *  pe -> li 居住关系
     * @param fromId
     * @param toId
     * @return
     */
    @Query(value = "match(a:pe),(b:li) where a.ids={fromId} and b.ids={toId}  merge (a) - [r:居住{direction:{direction}}]->(b)")
    Neo4jRelationInfo generateGraphDataRelation_JUZ(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction);

    /**
     *  pe -> pe 同事关系
     * @param fromId
     * @param toId
     * @return
     */
    @Query(value = "match(a:pe),(b:pe) where a.ids={fromId} and b.ids={toId}  merge (a) - [r:同事{direction:{direction}}]-(b)")
    Neo4jRelationInfo generateGraphDataRelation_TS(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction);



    /**
     *  pe -> wu 就职关系
     * @param fromId
     * @param toId
     * @return
     */
    @Query(value = "match(a:pe),(b:wu) where a.ids={fromId} and b.ids={toId}  merge (a) - [r:就职{direction:{direction}}]->(b)")
    Neo4jRelationInfo generateGraphDataRelation_JZGX(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction);


    /**
     *  pe -> sc 毕业院校关系
     * @param fromId
     * @param toId
     * @return
     */
    @Query(value = "match(a:pe),(b:sc) where a.ids={fromId} and b.ids={toId}  merge (a) - [r:毕业{direction:{direction}}]->(b)")
    Neo4jRelationInfo generateGraphDataRelation_BYYX(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction);


    /**
     *  pe -> pa 论文参与关系
     * @param fromId
     * @param toId
     * @return
     */
    @Query(value = "match(a:pe),(b:pa) where a.ids={fromId} and b.ids={toId}  merge (a) - [r:参与者{direction:{direction}}]->(b)")
    Neo4jRelationInfo generateGraphDataRelation_PA(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction);

    /**
     *  pe -> pa 论文合作关系
     * @param fromId
     * @param toId
     * @return
     */
    @Query(value = "match(a:pe),(b:pe) where a.ids={fromId} and b.ids={toId}  merge (a) - [r:论文合作{direction:{direction}}]->(b)")
    Neo4jRelationInfo generateGraphDataRelation_LWHZ(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction);



    /**
     * web查询接口,查询与当前节点为1的数据---根据节点编号,适用于登录第二次节点点击之后的查询
     */
    @Query(value = "match(a)-[r]-(b) where a.ids={qid} return a,r,b")
    List<Map<String,String>> queryRelationDataByIds(@Param("qid") String qid);

    /**
     * web查询接口,查询与当前节点为1的数据
     */
    @Query(value = "match(a:pe)-[r]-(b) where a.cardNo={cardNo} return a,r,b")
    List<Map<String,String>> queryRelationDataByCardNo(@Param("cardNo") String cardNo);

}

 

 

 

bean配置:

<!--初始化配置的Config-->
    <bean id="myConfiguration" class="com.audaque.module.graphData.neo4j.config.MyConfiguration">
        <constructor-arg name="driverClass" value="org.neo4j.ogm.drivers.http.driver.HttpDriver" index="0" type="java.lang.String"/>
        <constructor-arg name="driverURL" value="http://10.229.183.142:7474" index="1" type="java.lang.String"/>
        <constructor-arg name="userName" value="neo4j" index="2" type="java.lang.String"/>
        <constructor-arg name="password" value="123456" index="3" type="java.lang.String"/>
    </bean>

 

 通过上述的简单配置就在spring环境中搭建到了neo4j。

业务逻辑代码:

  1. 存储所有的节点,直接读取数据中的人员信息,学校信息,居住信息,教育信息,工作信息,5张表的数据直接save到neo4j,部分代码如下.

  

 /**
     * 初始化图数据需要的人员节点数据
     *
     * @param personBaseInfoRepository
     * @return
     */
    @Override
    public void resetNeo4jPersonBaseInfoNode(PersonBaseInfoRepository personBaseInfoRepository) {
        //查询人员节点列表
        List<PersonBaseInfo> personBaseInfos =  graphDataDao.queryPersonBaseInfo();

        for (PersonBaseInfo personBaseInfo :personBaseInfos){
            try {
                personBaseInfoRepository.save(personBaseInfo);
            }
            catch (Throwable t){
                //生成节点异常时,继续跳过。
                continue;
            }
        }
    }

 

初始化内部外部关心数据,代码如下:

 /********************************************开始初始化节点间关系的数据**********************************************/

    /**
     * 初始化五大节点间的关系数据。
     * @param neo4jRelationInfoRepository
     * @return
     */
    @Override
    public void resetAllRelationInfo(Neo4jRelationInfoRepository neo4jRelationInfoRepository) {
        long start = System.currentTimeMillis();
        //初始化人员-->工作关系,人员->学校;人员->论文;人员->住房信息4个主关系的数据。
        List<Map<String,Object>> lists = graphDataDao.queryEntityRelationInfo();
        //计算内部关系信息 ,同事,校友,邻居,合作者关系。
        Map<String,List<String>> schoolFriendMap = new ConcurrentHashMap<>(); //校友

        Map<String,List<String>> workTogetherMap = new ConcurrentHashMap<>(); //同事

        Map<String,List<String>> neighborMap = new ConcurrentHashMap<>();    //邻居
        Map<String,List<String>> collaboratorMap = new ConcurrentHashMap<>();//论文合作者
        for(Map<String,Object> map :lists){

            String userId = "";
            //获取人员信息
            if(StringUtils.isNoneEmpty((String)map.get("USERID")) && StringUtils.isNoneEmpty((String)map.get("USERNAME"))){
                //取工作单位字段 UNIT_ID , UNIT_NAME
                if(StringUtils.isNoneEmpty((String)map.get("UNIT_ID")) && StringUtils.isNoneEmpty((String)map.get("UNIT_NAME"))){
                    //插入就职关系
                    neo4jRelationInfoRepository.generateGraphDataRelation_JZGX((String)map.get("USERID"),(String)map.get("UNIT_ID"),(String)map.get("USERID")+"->"+(String)map.get("UNIT_ID"));

                    //处理同事关系
                    if(workTogetherMap.containsKey((String)map.get("UNIT_ID"))){
                        List<String> list = workTogetherMap.get((String)map.get("UNIT_ID"));
                        if(!list.contains((String)map.get("USERID"))){
                            list.add((String)map.get("USERID"));
                            workTogetherMap.put((String)map.get("UNIT_ID"),list);
                        }
                    }else{
                        List<String> lis = new ArrayList<String>();
                        lis.add((String)map.get("USERID"));
                        workTogetherMap.put((String)map.get("UNIT_ID"),lis);
                    }

                }
                //取学校字段 SCHOOL_ID , SCHOOL_NAME
                if(StringUtils.isNoneEmpty((String)map.get("SCHOOL_ID")) && StringUtils.isNoneEmpty((String)map.get("SCHOOL_NAME"))){
                    //插入毕业院校
                    neo4jRelationInfoRepository.generateGraphDataRelation_BYYX((String)map.get("USERID"),(String)map.get("SCHOOL_ID"),(String)map.get("USERID")+"->"+(String)map.get("SCHOOL_ID"));

                    //处理校友关系
                    if(schoolFriendMap.containsKey((String)map.get("SCHOOL_ID"))){
                        List<String> list = schoolFriendMap.get((String)map.get("SCHOOL_ID"));
                        if(!list.contains((String)map.get("USERID"))){
                            list.add((String)map.get("USERID"));
                            schoolFriendMap.put(this.schoolFriend,list);
                        }
                    }else{
                        List<String> lis = new ArrayList<String>();
                        lis.add((String)map.get("USERID"));
                        schoolFriendMap.put((String)map.get("SCHOOL_ID"),lis);
                    }

                }

                //取住房信息字段 HOUSE_ID , HOUSE_ADDR
                if(StringUtils.isNoneEmpty((String)map.get("HOUSE_ID")) && StringUtils.isNoneEmpty((String)map.get("HOUSE_ADDR"))){
                    //插入毕业院校
                    neo4jRelationInfoRepository.generateGraphDataRelation_JUZ((String)map.get("USERID"),(String)map.get("HOUSE_ID"),(String)map.get("USERID")+"->"+(String)map.get("HOUSE_ID"));

                    //处理邻居关系
                    if(neighborMap.containsKey((String)map.get("HOUSE_ID"))){
                        List<String> list = neighborMap.get((String)map.get("HOUSE_ID"));
                        if(!list.contains((String)map.get("USERID"))){
                            list.add((String)map.get("USERID"));
                            neighborMap.put((String)map.get("HOUSE_ID"),list);
                        }
                    }else{
                        List<String> lis = new ArrayList<String>();
                        lis.add((String)map.get("USERID"));
                        neighborMap.put((String)map.get("HOUSE_ID"),lis);
                    }
                }
                //取论文信息字段 LW_ID , LW_TITLE
                if(StringUtils.isNoneEmpty((String)map.get("LW_ID")) && StringUtils.isNoneEmpty((String)map.get("LW_TITLE"))){
                    //插入毕业院校
                    neo4jRelationInfoRepository.generateGraphDataRelation_PA((String)map.get("USERID"),(String)map.get("LW_ID"),(String)map.get("USERID")+"->"+(String)map.get("LW_ID"));
                    //处理合作者关系
                    if(collaboratorMap.containsKey((String)map.get("LW_ID"))){
                        List<String> list = collaboratorMap.get((String)map.get("LW_ID"));
                        if(!list.contains((String)map.get("USERID"))){
                            list.add((String)map.get("USERID"));
                            collaboratorMap.put((String)map.get("LW_ID"),list);
                        }
                    }else{
                        List<String> lis = new ArrayList<String>();
                        lis.add((String)map.get("USERID"));
                        collaboratorMap.put((String)map.get("LW_ID"),lis);
                    }
                }

            }
        }

        //开始剔除长度为1的数据,没有对应的关系。
        schoolFriendMap.forEach((key,value) -> {
            //独立个体无法形成关系,剔除
            if(((List<String>)value).size()<=1){
                schoolFriendMap.remove(key);
            }
        });
        workTogetherMap.forEach((key,value) -> {
            //独立个体无法形成关系,剔除
            if(((List<String>)value).size()<=1){
                workTogetherMap.remove(key);
            }
        });
        neighborMap.forEach((key,value) -> {
            //独立个体无法形成关系,剔除
            if(((List<String>)value).size()<=1){
                neighborMap.remove(key);
            }
        });
        collaboratorMap.forEach((key,value) -> {
            //独立个体无法形成关系,剔除
            if(((List<String>)value).size()<=1){
                collaboratorMap.remove(key);
            }
        });

        //开始遍历校友关系数据,生成节点。
        schoolFriendMap.forEach((key,value) -> {
            List<String> li = (List<String>)value;
            for(int st = 0;st<li.size() ; st++){
                for(int ss = li.size()-1;ss>st;ss--){
                    System.out.println("生成关系"+li.get(st)+"->"+li.get(ss));
                    neo4jRelationInfoRepository.generateGraphDataRelation_XY(li.get(st),li.get(ss),"<->");

                }
            }
        });
        //同事关系
        workTogetherMap.forEach((key,value) -> {
            List<String> li = (List<String>)value;
            for(int st = 0;st<li.size() ; st++){
                for(int ss = li.size()-1;ss>st;ss--){
                    System.out.println("生成关系"+li.get(st)+"->"+li.get(ss));
                    neo4jRelationInfoRepository.generateGraphDataRelation_TS(li.get(st),li.get(ss),"<->");

                }
            }
        });
        //邻居关系
        neighborMap.forEach((key,value) -> {
            List<String> li = (List<String>)value;
            for(int st = 0;st<li.size() ; st++){
                for(int ss = li.size()-1;ss>st;ss--){
                    System.out.println("生成关系"+li.get(st)+"->"+li.get(ss));
                    neo4jRelationInfoRepository.generateGraphDataRelation_LJ(li.get(st),li.get(ss),"<->");

                }
            }
        });
        //合作者关系
        collaboratorMap.forEach((key,value) -> {
            List<String> li = (List<String>)value;
            for(int st = 0;st<li.size() ; st++){
                for(int ss = li.size()-1;ss>st;ss--){
                    System.out.println("生成关系"+li.get(st)+"->"+li.get(ss));
                    neo4jRelationInfoRepository.generateGraphDataRelation_LWHZ(li.get(st),li.get(ss),"<->");

                }
            }
        });
        System.out.println("总共花费时间:" + (System.currentTimeMillis() - start) + "ms");

    }

 

 

然后Control中对外暴露三个接口, 1.初始化节点,  2.初始化关系。 就可以了。

然后通过浏览器直接可以看到图数据的结构,分享下我做出来的效果。

 

至此一个从数据库存入到neo4j数据库中,然后可以对外开放一个查询的接口,返回与之有关系并且深度为1的数据,方便其他系统展示,接口如下:

/**
     * web查询接口,查询与当前节点为1的数据---根据节点编号,适用于登录第二次节点点击之后的查询。
     */
    @Query(value = "match(a)-[r]-(b) where a.ids={qid} return a,r,b")
    List<Map<String,String>> queryRelationDataByIds(@Param("qid") String qid);

    /**
     * web查询接口,用户登录之后第一次查询,需根据身份证号码查询。第二次查询就直接会调用上一个查询。
     */
    @Query(value = "match(a:pe)-[r]-(b) where a.cardNo={cardNo} return a,r,b")
    List<Map<String,String>> queryRelationDataByCardNo(@Param("cardNo") String cardNo);

 

추천

출처www.cnblogs.com/kangz/p/10973981.html