我们接着 Neo4J图库的基础介绍(一) 继续介绍Neo4J图库。
JAX-RS是一个用于构建REST资源的Java API,可以使用JAX-RS注解装饰每一个扩展类,从而让服务器处理对应的http请求,附加注解可以用来控制请求和响应的格式,http头和URI模板的格式。
下面看一个服务器扩展实现的示例,允许客户端请求社交网络的两个成员之间的距离
@Path(”/distance”)/*注解规定请求URL以/distance开始*/
Public class SocialNetworkExtension{
private final ExecutionEngine executionEngine ;
/*@ Context GraphDatabaseSerivce db引用到一个数据*/
Public SocialNetworkExtension(@ Context GraphDatabaseSerivce db){
This. executionEngine =new ExecutionEngine (db);
}
@GET/*get请求*/
@produces(“text/plain”)
@Path(“/{name1}/{name2}”) /*匹配/distance/name1/name2,占位符*/
Public String getDistance(@PathParam(“name1”) String name1,@PathParam(“name2”) String name2){
String query=“start…”;
Map<String,Object> params=new HashMap<String,Object>();
params.put(“name1”,name1);
Params.put(“name2”,name2);
ExcutionResult result= executionEngine .execute(query,params);
Return String.valueof(result.columnAs(“depth”).next());
}}
数据结构:Neo4j将图数据存储在若干不同的存储文件中,每个存储文件包含特定部分的数据(如节点,联系,属性等),每个节点记录长度为9个字节,通过大小固定的记录可以快速查找到存储文件中的节点。一个节点的第一个字节是“是否在使用”的标志位。接下来的4个字节表示关联到该节点的第一个联系,最后4个字节表示该节点的第一个属性的ID。节点是几个指向联系和属性列表的指针。
像节点一样,联系存储区的记录的大小也是固定的,每个记录的长度为33个字节。每个联系记录包含联系的起始节点ID和结束节点ID,联系类型的指针,以及起始节点和结束节点的上一个联系和下一个联系。
要读取节点的属性,只需要从指向第一个属性的指针开始遍历单向链表结构。要查询一个节点的联系,可以从指向第一个联系的节点联系指针开始,顺着特定节点的联系的双向链表寻找。
可以使用联系关联的起始节点ID和结束节点ID检查他们的节点记录,用这些ID乘以节点记录的大小,就可以立即计算出每个节点在存储文件中的偏移量
属性记录也是大小固定的,每个属性记录包括4个属性块和属性链中下一个属性的ID(属性的链表是单向的)
服务器集群模式: Neo4j HA模式总有单个master,零个或多个slave。与其他ms复制架构,Neo4j HA的slave可以处理写操作,而无需重定向写入到master。
Neo4j HA使用Apache ZooKeeper来进行master选举和服务器间状态信息传播。ZooKeeper可以看做是分布式服务协调器。Neo4j HA集群需要依赖ZooKeeper进程初始主选择,新master选举和集群内服务器状态报告。当master故障,新的master将自动选举。当 master故障,任何写事务都将回滚,并且在master选举期间,任何写操作都不会发生。 ZooKeeper需要大量ZooKeeper实例从而保证正常运行。这就意味着zookeeper实例应该永远是个奇数。
Neo4j HA使用Apache ZooKeeper来进行master选举和服务器间状态信息传播。ZooKeeper可以看做是分布式服务协调器。Neo4j HA集群需要依赖ZooKeeper进程初始主选择,新master选举和集群内服务器状态报告。当master故障,新的master将自动选举。当 master故障,任何写事务都将回滚,并且在master选举期间,任何写操作都不会发生。 ZooKeeper需要大量ZooKeeper实例从而保证正常运行。这就意味着zookeeper实例应该永远是个奇数。
查询语法(Cyphe Query Language)
neo4j自己基于图论的搜索算法,实现了一套查询语言解析,提供了一些常见的聚合函数(max,sum,min,count等)。
Ø START:在图中的开始点,通过元素的ID或所以查找获得。
Ø MATCH:图形的匹配模式,束缚于开始点。
Ø WHERE:过滤条件。
Ø RETURN:返回所需要的。
Ø START:在图中的开始点,通过元素的ID或所以查找获得。
Ø MATCH:图形的匹配模式,束缚于开始点。
Ø WHERE:过滤条件。
Ø RETURN:返回所需要的。
Ø CREATE:创建节点或者关系
Ø DELETE:删除节点、关系或者属性
Ø SET:设置属性的值 FOREACH:对list中的元素一次一 个的执行操作( Performs updating actions once per element in a list)
Ø WITH:切分一个query成多个不同的部分
通过索引找到一个名叫'John'的用户,并遍历图找到他的朋友的朋友,返回John和这些朋友的信息
START john=node:node_auto_index(name = 'John')
MATCH john-[:friend]->()-[:friend]->fof
RETURN john, fof
模糊查询节点id属性中包含11的,的节点。
START ne=node:ne('id=*11*')
START ne=node:ne('id=*11*')
return ne
条件,模糊查询。查询 label 含中山的网元
start n=node(3) match n-[:NE]-ne where ne.label =~ '.*中山.*'
start n=node(3) match n-[:NE]-ne where ne.label =~ '.*中山.*'
return ne.id, ne.label, ne.name;
根据索引为nePort,针对id模糊查询全部节点。根据id排序,limit只取前10条记录
start n = node:nePort('id:*')
match (x)-[:NE_PORT]->(n)
return n,x
order by n.id limit 10
start n = node:nePort('id:*')
match (x)-[:NE_PORT]->(n)
return n,x
order by n.id limit 10
Spring Data Neo4j:为Spring开发人员提供了熟悉的方式与Neo4j进行交互,使用基于注解的方式与Spring的框架进行集成。在POJO(简单java对象,Plain Old Java Object)实体及其域上添加一些注解,这样Spring Data Neo4j就能将Java对象映射为图元素,这些实体的注解通过节点(@NodeEntity)和关系(@RelationshipEntity)来实现,域上注解声明了与其它实体的关系(@RelatedTO),自定义转换,自动标引(@Indexed)或者计算出的/衍生的值(@Query),Spring Data Neo4j允许我们存储实体的类型信息(继承体系),从而可以执行一些高级的操作和类型的转换。
@NodeEntity
public class World {
private final static String REACHABLE_BY_ROCKET = "REACHABLE_BY_ROCKET";
@GraphId
private Long id;
// Uses default schema based index
@Indexed
private String name;
// Uses legacy index mechanism
@Indexed(indexType = IndexType.SIMPLE)
private int moons;
@Fetch
@RelatedTo(type = REACHABLE_BY_ROCKET, direction = Direction.BOTH)
private Set<World> reachableByRocket;
Spring Data Neo4j的核心是Neo4jTemplate,它提供了(类似与JdbcTemplate)各种低层级的功能,这些功能对Neo4j API进行了封装以支持所匹配的领域对象。Spring Data Neo4j通过两个XML命名空间元素来进行配置,用来进行通用开发的搭建和Repository的配置。
Spring Data Neo4j支持嵌入式模式和服务器模式,服务器模式要通过Neo4j的Java Rest API绑定来进行访问
Org.springframe work.data:spring-data-neo4j
<dependencies>
<!-- SDN for simple mapping mode -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>${spring-data-neo4j.version}</version>
</dependency>
…
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-kernel</artifactId>
<version>${neo4j.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>
•嵌入式模式
•<?xml version="1.0" encoding="UTF-8" standalone="no"?>
•<beans xmlns="http://www.springframework.org/schema/beans"
• xmlns:context="http://www.springframework.org/schema/context"
• xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
• xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
• xmlns:tx="http://www.springframework.org/schema/tx"
•……">
•<context:spring-configured/>
• <context:annotation-config/>
• <context:component-scan base-package="org.springframework.data.neo4j.examples.hellograph" />
•<!—建立一个图数据库>
• <neo4j:config storeDirectory="target/neo4j-db-plain"
• base-package="org.springframework.data.neo4j.examples.hellograph.domain"/>
<neo4j:repositories base-package="org.springframework.data.neo4j.examples.hellograph.repositories"/>
•<tx:annotation-driven />
•</beans>
•服务器模式
•<?xml version="1.0" encoding="UTF-8" standalone="no"?>
•<beans xmlns="http://www.springframework.org/schema/beans"
• xmlns:context="http://www.springframework.org/schema/context"
• xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
• xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
• xmlns:tx="http://www.springframework.org/schema/tx"
•……">
•<neo4j:config graphDatabaseService=“graphDatabaseService”/>
•<bean id=“graphDatabaseService”
•class=“org.springframework.data.neo4j.rest.SpringRestGraphDatabase”>
•<constructor index=“0” value=“http://10.168.104.159:7474/db/data”>
•</bean>
•</beans>
Repository 数据访问层,为了让代码变得更加简单,Spring Data在Template的基础上提供了一个存储( repository )抽象,这样可以减少数据访问对象在实现一个普通接口时去定义通用场景的代价。
public class Customer{
private long id;
private String firstname;
private String lastname;
private Address address;
}
通过传统的方式至少需要实现一个存储类,包含基本的CRUD(create,read,Update和delete
)方法,以及通过限制条件来访问实体子集的查询方法。
使用Spring Data Repository 的方式能够避免大多数的代码,只需要为这个实体存储声明简单的接口定义即可。
Public interface customerRepository extends Repository<Customer,long>{
……
}
激活Spring Data Repository
…
<beans:beans xmlns:……>
<jpa:repositories base-package=“com.XXX. repositoy” >
</beans>
package org.springframework.data.neo4j.examples.hellograph.repositories;
import org.springframework.data.neo4j.examples.hellograph.domain.World;
import org.springframework.data.neo4j.repository.GraphRepository;
public interface WorldRepository extends GraphRepository<World> {}
1.声明持久层的接口,该接口继承 Repository,Repository 是一个标记型接口,它不包含任何方法,当然如果有需要,Spring Data 也提供了若干 Repository 子接口,其中定义了一些常用的增删改查,以及分页相关的方法。
2.在接口中声明需要的业务方法。Spring Data 将根据给定的策略来为其生成实现代码。
3.在 Spring 配置文件中增加一行声明,让 Spring 为声明的接口创建代理对象。配置了 <jpa:repositories> 后,Spring 初始化容器时将会扫描 base-package 指定的包目录及其子目录,为继承 Repository 或其子接口的接口创建代理对象,并将代理对象注册为 Spring Bean,业务层便可以通过 Spring 自动封装的特性来直接使用该对象。
此外,<jpa:repository> 还提供了一些属性和子标签,便于做更细粒度的控制。可以在 <jpa:repository> 内部使用 <context:include-filter>、<context:exclude-filter> 来过滤掉一些不希望被扫描到的接口。
Spring Data JPA——参考文档
http://jpa.coding.io/