<转>Neo4j结合Spring Data Graph的例子

sushaning 2011-10-11

原文地址:http://www.openfetion.com/category/neo4j.aspx

在spring中使用neo4j

<转>Neo4j结合Spring Data Graph的例子 四月 19, 2010 08:07 by <转>Neo4j结合Spring Data Graph的例子 Terry

从neo4j官方网站http://neo4j.org/下载neo4j-apoc包,或者自己获取源码自行打包也可。

我使用的是java开发工具是SpringToolSuite,新建一个springwebmvc项目,模板引擎使用velocity(velocity.apache.org),web.xml配置:

<?xmlversion="1.0"encoding="UTF-8"?>

<web-appxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns="http://java.sun.com/xml/ns/javaee"xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

id="attentiondb"version="2.5">

<display-name>attentiondb</display-name>

<!--

EnablescleanURLswithJSPviewse.g./welcomeinsteadof

/app/welcome

-->

<filter>

<filter-name>UrlRewriteFilter</filter-name>

<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>UrlRewriteFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<!--Handlesallrequestsintotheapplication-->

<servlet>

<servlet-name>SpringMVCDispatcherServlet</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<init-param>

<param-name>contextConfigLocation</param-name>

<param-value>

/WEB-INF/spring/app-config.xml

</param-value>

</init-param>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>SpringMVCDispatcherServlet</servlet-name>

<url-pattern>/attentiondb/*</url-pattern>

</servlet-mapping>

</web-app>

在/WEB-INF/spring/app-config.xml中配置neo4jbean(这里需要注意spring2.5与3.0的区别,3.0中使用map元素代替util:map元素):

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd

http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsd">

<!--

Scanstheclasspathofthisapplicationfor@Componentstodeployas

beans

-->

<context:component-scanbase-package="attentiondb"/>

<beanid="graphDbService"class="org.neo4j.kernel.EmbeddedGraphDatabase"

init-method="enableRemoteShell"destroy-method="shutdown">

<constructor-argindex="0"value="d://attentiondb"/>

<constructor-argindex="1">

<map>

<entrykey="create"value="false"/>

<entrykey="neostore.nodestore.db.mapped_memory"value="20M"/>

<entrykey="neostore.propertystore.db.mapped_memory"value="90M"/>

<entrykey="neostore.nodestore.db.mapped_memory"value="1M"/>

<entrykey="neostore.nodestore.db.mapped_memory"value="1M"/>

<entrykey="neostore.nodestore.db.mapped_memory"value="130M"/>

<entrykey="neostore.nodestore.db.mapped_memory"value="100M"/>

</map>

</constructor-arg>

</bean>

<beanid="indexService"class="org.neo4j.index.lucene.LuceneIndexService"

destroy-method="shutdown">

<constructor-argindex="0"ref="graphDbService"/>

</bean>

<beanid="velocityConfig"

class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">

<propertyname="resourceLoaderPath"value="/WEB-INF/views/"/>

</bean>

<beanid="viewResolver"

class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">

<propertyname="cache"value="true"/>

<propertyname="prefix"value=""/>

<propertyname="suffix"value=".vm"/>

</bean>

<!--ApplicationMessageBundle-->

<beanid="messageSource"

class="org.springframework.context.support.ReloadableResourceBundleMessageSource">

<propertyname="basename"value="/WEB-INF/messages/messages"/>

<propertyname="cacheSeconds"value="0"/>

</bean>

<!--ConfiguresSpringMVC-->

<importresource="mvc-config.xml"/>

</beans>

第一个打分

neo4j处理好友关系

<转>Neo4j结合Spring Data Graph的例子 四月 1, 2010 16:44 by <转>Neo4j结合Spring Data Graph的例子 Terry

在实际业务中,我们经常遇到这样的场景,比如查找好友的好友。处理此类业务,neo4j体现出了方便快捷强大的功能。

比如我们有九个人:

IdName

1梁1

2梁2

3梁3

4梁4

5梁5

6梁6

7梁7

8梁8

9梁9

其中:梁1、梁2认识所有的人,梁9认识梁1、梁2、梁8

我们要实现查找梁9的好友的好友(不包括自身和直接好友)。

首先定义好友关系枚举:

publicenumFriendRelationTypesimplementsRelationshipType{

KNOWS

}

创建上述好友关系graphdatabase:

ArrayList<Node>nodes=newArrayList<Node>(9);

Map<String,String>props=newHashMap<String,String>();

//props.put("create","false");

GraphDatabaseServicegraphDb=newEmbeddedGraphDatabase("var/base",

props);

Transactiontx=graphDb.beginTx();

try{

for(inti=0;i<9;i++){

Nodenode=graphDb.createNode();

node.setProperty("Id",i+1);

node.setProperty("Name","梁"+i);

nodes.add(node);

}

Nodenode1=nodes.get(0);

Nodenode2=nodes.get(1);

Nodenode9=nodes.get(8);

for(inti=2;i<9;i++){

Nodenode=nodes.get(i);

node.createRelationshipTo(node1,FriendRelationTypes.KNOWS);

node.createRelationshipTo(node2,FriendRelationTypes.KNOWS);

}

nodes.get(7).createRelationshipTo(node9,FriendRelationTypes.KNOWS);

tx.success();

}catch(Exceptionex){

ex.printStackTrace();

}finally{

tx.finish();

graphDb.shutdown();

}

显示所有的好友,查找梁9的好友并显示:

Map<String,String>props=newHashMap<String,String>();

props.put("create","false");

GraphDatabaseServicegraphDb=newEmbeddedGraphDatabase("var/base",

props);

Transactiontx=graphDb.beginTx();

try{

Iterable<Node>nodes=graphDb.getAllNodes();

for(Nodenode:nodes){

if(node.hasProperty("Id")){

System.out.println("NodeId:"+node.getId()+"Id:"

+node.getProperty("Id")+"Name:"

+node.getProperty("Name"));

}

}

Nodenode=graphDb.getNodeById(9);

Traverserfriends=node.traverse(Traverser.Order.BREADTH_FIRST,

StopEvaluator.END_OF_GRAPH,newReturnableEvaluator(){

publicbooleanisReturnableNode(TraversalPositionpos){

System.out.println(pos.depth());

returnpos.depth()!=1&&pos.notStartNode();

}

},FriendRelationTypes.KNOWS,Direction.BOTH);

for(Nodefriend:friends){

System.out.println("Id:"+friend.getProperty("Id")+"Name:"

+friend.getProperty("Name"));

}

tx.success();

}finally{

tx.finish();

graphDb.shutdown();

}

在这里我们可以看到Traverser的简单应用。在neo4j查找中,需要先找到一个根节点,然后再这个根节点上创建Traverser来进行各种查询。

第一个打分

neo4j初体验

<转>Neo4j结合Spring Data Graph的例子 三月 31, 2010 03:51 by <转>Neo4j结合Spring Data Graph的例子 Terry

neo4j(http://neo4j.org/)一个开源的图数据库graph database。neo4j是基于磁盘文件、内嵌、支持java事务JTS,用于存储图结构数据的数据库引擎。具体的资料可以查看官方网站。

neo4j的存储结构中重点的就是Node(节点)和Relationship(关系)。Node与Node之间通过Relationship连接,Node与Node之间可以具有多种关系,但是两个Node不能相同。

下面通过一个具体的业务来演示一下neo4j的简单使用。

我们需要来存储用户与用户之间都有过什么关系,关系之间有什么样的权重,这样通过用户之间的关系和关系的权重,在此基础上我们可以分析用户之间的关注度。在数据中是这样存储的:

relation关系表,用来枚举用户之间可能存在的关系,及关系的自定义权重

1发表文章评论3

2回复文章评论1

3喜欢文章1

4文章点名50

5留言10

6回复留言3

7评论留言飞语5

8回复留言飞语评论5

9收藏留言飞语3

10评论图片3

11回复图片评论3

12图片圈人20

13分享20

14站内信2

15回复站内信2

graphs用户关系系表,存储两个用户之间都具有什么样的关系。有三个字段:BeginUserId开始用户Id、EndUserId结束用户Id、Reason原因。其中Reason是xml格式数据,记录了用户Id为EndUserId对用户Id为BeginUserId发生过什么行为,产生过什么样的关系,如14905781812960721<at="3"e="1"/><at="13"e="20"/>,表明用户18129607对用户1490578曾经回复留言、喜欢文章,e可以次数以表示权重。

以下是如何通过neo4j来创建此业务的graphdatabase,实际graphs表中有600万左右的数据,我们为了演示只取前1000条,并且只是通过neo4jkernel核心包来创建。

创建AttentionRelationTypes枚举,实现接口RelationshipType,这是必须的。节点直接的Relationship是通过RelationshipType的不同名称来定义并区分的。

packageeasynet.neo4j;

importorg.neo4j.graphdb.RelationshipType;

/*

*关注关系

*/

publicenumAttentionRelationTypesimplementsRelationshipType{

PublishedComments,ReplyToComment,FavoriteArticle,ArticleMention,Message,ReplyToMessage,CommentOnMood,ReplyToMoodComments,FavoriteMood,CommentOnPicture,ReplyToPictureComments,CirclePicture,Share,SiteMessage,ReplyToSiteMessage

}

很重要的一点,由于neo4j是自己维护Node的Id,我们不能把UserId当作Node的Id,而只能作为一个Node的Property。但是因为我们在业务上需要保证作为用户Node的唯一性,所以创建一个用来维护UserId与NodeId的对应关系表:usernode(有两个字段UserId、NodeId)。定义一个类NodeStore用来分装此操作。

packageeasynet.neo4j;

importjava.sql.*;

importnet.sourceforge.jtds.jdbcx.*;

publicclassNodeStore{

privateJtdsDataSourcedataSource=null;

privateStringinsertQuery="{call[UserNode_Create](?,?)}";

privateStringgetNodeIdQuery="{call[UserNode_GetNodeIdByUserId](?)}";

publicNodeStore(JtdsDataSourcedataSource){

this.dataSource=dataSource;

}

publicvoidstore(intuserId,longnodeId)throwsSQLException{

Connectioncon=dataSource.getConnection();

CallableStatementcst=con.prepareCall(insertQuery);

cst.setInt(1,userId);

cst.setLong(2,nodeId);

cst.execute();

cst.close();

}

publiclonggetNodeIdByUserId(intuserId)throwsSQLException{

intnodeId=0;

Connectioncon=dataSource.getConnection();

CallableStatementcst=con.prepareCall(getNodeIdQuery);

cst.setInt(1,userId);

ResultSetrs=cst.executeQuery();

while(rs.next()){

nodeId=rs.getInt("NodeId");

}

cst.close();

returnnodeId;

}

}

下面就是具体通过neo4j创建graphdatabase的代码了:

packageeasynet.neo4j;

importjava.io.*;

importjava.sql.*;

importjava.util.*;

importorg.w3c.dom.*;

importorg.xml.sax.InputSource;

importorg.xml.sax.SAXException;

importjavax.xml.parsers.*;

importnet.sourceforge.jtds.jdbcx.*;

importorg.neo4j.graphdb.*;

importorg.neo4j.graphdb.Node;

importorg.neo4j.kernel.*;

importorg.neo4j.kernel.impl.traversal.*;

publicclassAttentionRelationShell{

/**

*处理关注关系

*

*@throwsSQLException

*/

publicstaticvoidmain(String[]args){

JtdsDataSourcedataSource=newJtdsDataSource();

dataSource.setServerName("192.168.1.100");

dataSource.setPortNumber(1433);

dataSource.setDatabaseName("yadong_temp");

dataSource.setUser("sa");

dataSource.setPassword("devterry");

NodeStorenodeStore=newNodeStore(dataSource);

longbeginTime=System.currentTimeMillis();

System.out.println("开始创建...");

Map<String,String>props=newHashMap<String,String>();

//props.put("create","false");

GraphDatabaseServicegraphDb=newEmbeddedGraphDatabase("var/base",

props);

try{

Connectioncon=dataSource.getConnection();

Statementst=con.createStatement();

ResultSetrs=st

.executeQuery("SELECT[BeginUserId],[EndUserId],[Reason]FROM[graphs]");

while(rs.next()){

intbeginUserId=rs.getInt("BeginUserId");

intendUserId=rs.getInt("EndUserId");

Stringreason=rs.getString("Reason");

System.out.println("beginUserId:"+beginUserId

+"endUserId:"+endUserId);

NodebeginUserNode=null;

NodeendUserNode=null;

Transactiontx=graphDb.beginTx();

try{

longbeginNodeId=nodeStore.getNodeIdByUserId(beginUserId);

longendNodeId=nodeStore.getNodeIdByUserId(endUserId);

if(beginNodeId!=0){

beginUserNode=graphDb.getNodeById(beginNodeId);

}else{

beginUserNode=graphDb.createNode();

beginUserNode.setProperty("UserId",beginUserId);

nodeStore.store(beginUserId,beginUserNode.getId());

}

if(endNodeId!=0){

endUserNode=graphDb.getNodeById(endNodeId);

}else{

endUserNode=graphDb.createNode();

endUserNode.setProperty("UserId",endUserId);

nodeStore.store(endUserId,endUserNode.getId());

}

try{

DocumentBuilderFactoryfactory=DocumentBuilderFactory

.newInstance();

DocumentBuilderbuilder=factory.newDocumentBuilder();

StringReadersr=newStringReader("<relation>"

+reason+"</relation>");

InputSourceis=newInputSource(sr);

Documentdoc=builder.parse(is);

NodeListnodes=doc.getElementsByTagName("a");

//创建用户Node之间的Relationship

for(inti=0;i<nodes.getLength();i++){

org.w3c.dom.Nodenode=nodes.item(i);

NamedNodeMapattributes=node.getAttributes();

intrealtionTypeId=Integer.parseInt(attributes

.getNamedItem("t").getNodeValue());

intweight=Integer.parseInt(attributes

.getNamedItem("e").getNodeValue());

AttentionRelationTypesrelationTypes=AttentionRelationTypes.PublishedComments;

switch(realtionTypeId){

case1:

relationTypes=AttentionRelationTypes.PublishedComments;

break;

case2:

relationTypes=AttentionRelationTypes.ReplyToComment;

break;

case3:

relationTypes=AttentionRelationTypes.FavoriteArticle;

break;

case4:

relationTypes=AttentionRelationTypes.ArticleMention;

break;

case5:

relationTypes=AttentionRelationTypes.Message;

break;

case6:

relationTypes=AttentionRelationTypes.ReplyToMessage;

break;

case7:

relationTypes=AttentionRelationTypes.CommentOnMood;

break;

case8:

relationTypes=AttentionRelationTypes.ReplyToMoodComments;

break;

case9:

relationTypes=AttentionRelationTypes.FavoriteMood;

break;

case10:

relationTypes=AttentionRelationTypes.CommentOnPicture;

break;

case11:

relationTypes=AttentionRelationTypes.ReplyToPictureComments;

break;

case12:

relationTypes=AttentionRelationTypes.CirclePicture;

break;

case13:

relationTypes=AttentionRelationTypes.Share;

break;

case14:

relationTypes=AttentionRelationTypes.SiteMessage;

break;

case15:

relationTypes=AttentionRelationTypes.ReplyToSiteMessage;

break;

}

RelationshiprelationShip=endUserNode

.createRelationshipTo(beginUserNode,

relationTypes);

relationShip.setProperty("weight",weight);

}

}catch(Exceptionex){

ex.printStackTrace();

}

}finally{

tx.success();

tx.finish();

}

}

}catch(SQLExceptionex){

ex.printStackTrace();

}finally{

graphDb.shutdown();

}

System.out.println("完成共用时:"

+(System.currentTimeMillis()-beginTime));

}

}

相关推荐