天天看点

NOSQL图形数据库 - Neo4j

Neo4j入门指南
    • 1、简介
    • 2、特点
    • 3、安装
    • 4、基础操作
    • 5、Java集成
      • 5.1 内嵌数据库集成方式
      • 5.2 服务器集成方式
      • 5.3 Spring集成方式
    • 参考文档

1、简介

Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中。它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储在网络(从数学角度叫做图)上而不是表中。Neo4j也可以被看作是一个高性能的图引擎,该引擎具有成熟数据库的所有特性。程序员工作在一个面向对象的、灵活的网络结构下而不是严格、静态的表中——但是他们可以享受到具备完全的事务特性、企业级的数据库的所有好处。

2、特点

  1. 对象关系的不匹配使得把面向对象的“圆的对象”挤到面向关系的“方的表”中是那么的困难和费劲,而这一切是可以避免的。
  2. 关系模型静态、刚性、不灵活的本质使得改变schemas以满足不断变化的业务需求是非常困难的。由于同样的原因,当开发小组想应用敏捷软件开发时,数据库经常拖后腿。
  3. 关系模型很不适合表达半结构化的数据——而业界的分析家和研究者都认为半结构化数据是信息管理中的下一个重头戏。
  4. 网络是一种非常高效的数据存储结构。人脑是一个巨大的网络,万维网也同样构造成网状,这些都不是巧合。关系模型可以表达面向网络的数据,但是在遍历网络并抽取信息的能力上关系模型是非常弱的。

3、安装

从Docker Hub上pull一个Neo4j的镜像

docker pull neo4j
           

启动一个Neo4j的容器, 在Home目录下建立一个/neo4j/data文件夹用于存放数据

docker run -d 
    --name neo4j 
    --publish=: 
    --publish=: 
    --volume=$HOME/neo4j/data:/data 
    neo4j
           

在浏览器中访问 http://ipaddress:7474 可以看到如下的UI界面,输入默认用户名和密码neo4j即可连接到neo4j数据库。

NOSQL图形数据库 - Neo4j

4、基础操作

Neo4j使用Cypher语法操作数据库,CRUD示例

创建节点

CREATE (e:Country{name:"中国"})
CREATE (e1:Country{name:"美国"})
CREATE (c:Company{name:"腾讯",createtime:"2000-12-20"})
CREATE (c1:Company{name:"苹果",createtime:"2002-07-08"})
CREATE (c2:Company{name:"阿里",createtime:"2004-12-20"})
CREATE (c3:Company{name:"美团",createtime:"2010-12-20"})
CREATE (c4:Company{name:"亚马逊",createtime:"2007-07-08"})
           

创建关系

MATCH (e:Country) WHERE e.name="中国" MATCH (c:Company) WHERE c.name="腾讯" CREATE (c)-[r:BELONG_TO]->(e) RETURN e,c,r
MATCH (e:Country) WHERE e.name="中国" MATCH (c:Company) WHERE c.name="美团" CREATE (c)-[r:BELONG_TO]->(e) RETURN e,c,r
MATCH (e:Country) WHERE e.name="中国" MATCH (c:Company) WHERE c.name="阿里" CREATE (c)-[r:BELONG_TO]->(e) RETURN e,c,r
MATCH (e:Country) WHERE e.name="美国" MATCH (c:Company) WHERE c.name="亚马逊" CREATE (c)-[r:BELONG_TO]->(e) RETURN e,c,r
MATCH (e:Country) WHERE e.name="美国" MATCH (c:Company) WHERE c.name="苹果" CREATE (c)-[r:BELONG_TO]->(e) RETURN e,c,r
MATCH (e:Country{name:"中国"}) MATCH (e1:Country{name:"美国"}) CREATE (e)-[r:PARTNER{desc:"成为合作伙伴",time:"2000-02-08"}]->(e1) RETURN e,e1,r
MATCH (e:Country{name:"中国"}) MATCH (e1:Country{name:"美国"}) CREATE (e1)-[r:PARTNER{desc:"成为合作伙伴",time:"2000-02-08"}]->(e) RETURN e,e1,r
           

查询节点、关系

# 查询 Company 类型的节点
MATCH (e:Company) RETURN e
MATCH (e:Company) RETURN e.name,e.createtime LIMIT 
# 查询所有的节点
MATCH (n) RETURN n LIMIT 

# 查询 BELONG_TO 类型的关系
MATCH p=()-[r:BELONG_TO]->() RETURN p LIMIT 
MATCH (e:Company{name:"美团"})-[r]-(e1:Country{name:"中国"}) RETURN e,r,e1
# 查询所有的关系
MATCH p=()-->() RETURN p LIMIT 
           

删除节点、关系

# 删除节点(删除节点前,需保证该节点不存在关系)
MATCH (e:Company) WHERE e.name="美团" DELETE e
# 仅仅删除`美团`与`中国`之间的关系
MATCH (e:Company{name:"美团"})-[r]-(e1:Country{name:"中国"}) DELETE r
# 删除`美团`与`中国`节点以及他们之间的关系
MATCH (e:Company{name:"美团"})-[r]-(e1:Country{name:"中国"}) DELETE e,r,e1
# 删除关系为BELONG_TO的节点以及他们的关系
MATCH p=()-[r:BELONG_TO]->() DELETE p
# 删除所有存在关系的节点以及他们之间的关系
MATCH p=()-->() DELETE p
           

修改节点、关系属性

MATCH (e:Company) WHERE e.name="美团" SET e.name="美团点评" RETURN e
MATCH (e:Company{name:"美团点评"})-[r]->(c:Country) SET r.name="属于"  RETURN e,r,c
           

5、Java集成

5.1 内嵌数据库集成方式

所需依赖

示例代码

public static void main(String[] args) throws Exception {
        GraphDatabaseFactory dbFactory = new GraphDatabaseFactory();
        GraphDatabaseService db = dbFactory.newEmbeddedDatabase(new File("E:/TPNeo4jDB"));
        try (Transaction tx = db.beginTx()) {
            Node javaNode = db.createNode(Tutorials.JAVA);
            javaNode.setProperty("TutorialID", "JAVA001");
            javaNode.setProperty("Title", "Learn Java");
            javaNode.setProperty("NoOfChapters", "25");
            javaNode.setProperty("Status", "Completed");

            Node scalaNode = db.createNode(Tutorials.SCALA);
            scalaNode.setProperty("TutorialID", "SCALA001");
            scalaNode.setProperty("Title", "Learn Scala");
            scalaNode.setProperty("NoOfChapters", "20");
            scalaNode.setProperty("Status", "Completed");

            Relationship relationship = javaNode.createRelationshipTo
                    (scalaNode, TutorialRelationships.JVM_LANGIAGES);
            relationship.setProperty("Id", "1234");
            relationship.setProperty("OOPS", "YES");
            relationship.setProperty("FP", "YES");

            tx.success();
        }
        System.out.println("Done successfully");
    }

public enum Tutorials implements Label {
    JAVA, SCALA, SQL, NEO4J,;
}

public enum TutorialRelationships implements RelationshipType {
    JVM_LANGIAGES, NON_JVM_LANGIAGES;
}
           

5.2 服务器集成方式

所需依赖

示例代码

public static void main(String[] args) throws Exception {
        Driver driver = GraphDatabase.driver("bolt://192.168.15.145:7687", AuthTokens.basic("neo4j", "123456"));
        Session session = driver.session();
        Map<String, Object> saveMap = new HashMap<>();
        saveMap.put("name", "Arthur001");
        saveMap.put("title", "King001");
        session.run("CREATE (a:Person {name: {name}, title: {title}})", saveMap);

        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("name", "Arthur001");
        StatementResult result = session.run("MATCH (a:Person) WHERE a.name = {name} " +
                "RETURN a.name AS name, a.title AS title", queryMap);
        while (result.hasNext()) {
            Record record = result.next();
            System.out.println(record.get("title").asString() + " " + record.get("name").asString());
        }
        session.close();
        driver.close();
    }
           

5.3 Spring集成方式

所需依赖

示例代码

Domain Entities

@NodeEntity
public class Movie {

  @Id @GeneratedValue Long id;
  String title;

  Person director;

  @Relationship(type="ACTS_IN", direction = Relationship.INCOMING)
  Set<Person> actors;

  @Relationship(type = "RATED")
  List<Rating> ratings;
}
           

Repositories

interface MovieRepository extends Neo4jRepository<Movie, Long> {

  // derived finder
  Movie findByTitle(String title);

  @Query("MATCH (m:Movie)<-[rating:RATED]-(user) WHERE id(movie)={movie} return rating")
  List<Rating> getRatings(@Param("movie") Movie movie);

  // Co-Actors
  Set<Person> findByActorsMoviesActorName(String name);

  @Query("MATCH (movie:Movie)-[:HAS_GENRE]->(genre)<-[:HAS_GENRE]-(similar)
          WHERE id(movie) = {0} RETURN similar")
  List<Movie> findSimilarMovies(Movie movie);
}
           

Configuration

@Configuration
@EnableTransactionManagement
@ComponentScan("org.neo4j.cineasts")
@EnableNeo4jRepositories("org.neo4j.cineasts.repository")
public class PersistenceContext {

  @Bean
  public SessionFactory getSessionFactory() {
    return new SessionFactory(configuration(), "org.neo4j.cineasts.domain");
  }

  @Bean
  public Neo4jTransactionManager transactionManager() throws Exception {
    return new Neo4jTransactionManager(getSessionFactory());
  }

  @Bean
  public org.neo4j.ogm.config.Configuration configuration() {
    return new org.neo4j.ogm.config.Configuration.Builder()
      .uri("bolt://localhost")
      .build();
  }
}
           

Example

@Autowired MovieRepository repo;

Iterable<Movie> movies = repo.findAll();
Movie movie = repo.findByTitle("The Matrix");
repo.save(movie);

List<Rating> ratings = repo.getRatings(movie);
           

参考文档

  • Neo4j官方连接:https://neo4j.com/
  • w3c教程:https://www.w3cschool.cn/neo4j/
  • Spring-Data-Neo4j: https://projects.spring.io/spring-data-neo4j/