本帖最后由 evababy 于 2017-4-12 15:42 编辑
最近研究neo4j,犯懒了不整理格式了,
neo4j介绍直接网上找,此处忽略,只介绍从导入数据。
官网最新版本3.1.3,建议直接用服务器版本,别去研究window版本,大体功能一样,没离线导入。强烈推荐neo4j的控制台,是见过所有软件、产品中最棒的!
社区版本地址如下:(具体收费有啥限制没细查,文件来源于官网)
http://download.csdn.net/detail/yanji94521/9810890
需要JDK1.8否则启动报错
修改配置文件,服务监听地址,放开无法远程访问,neo4j.db是库文件目录,为了后续的切换使用。其他性能参数自己研究吧
dbms.connectors.default_listen_address=0.0.0.0
dbms.active_database=neo4j.db
启停也很简单,遗憾的是不能指定conf,所以我们制定了一个默认的neo4j.db(后续使用软链接进行切换,另外用NG切换应该也是可行的)
neo4j { console | start | stop | restart | status }
http://ip:7474 默认密码neo4j,首次登陆需要强制修改密码
网上有朋友总结neo4j支持5中导入数据的方式,其中2种在线,3种离线,在线的一是通过API用程序代码导入,效率极低,另外是通过cypher语句导入csv文件,效率略好,但是无法满足千万以上数据,而离线的一种是自身支持的neo4j-import导入,千万级关系数据1分钟导入(2和2G破虚拟机下进行的),其他两种均为第三方没研究过。
neo4j这玩应是所以推广不开也是有很多弊端的,比如import时要求不同标签的id必须唯一,对于关系型数据库来说,各表用自增主键怎么地吧,可惜到neo4j这的import都乖乖的加前后缀吧。neo4j的解释是:当建立关系时候需要根据ID去找节点,所以ID要唯一。
本次我们主要使用cypher和neo4j-import方式导入,都是基于csv文件导入的。
cypher方式
据说底层也是scala解析的
csv文件不包含头信息,本人严重不喜欢文件中包含头信息,考虑实际环境中可能不便生成头,如果在hadoop下生成csv数据时,增加头就是一件很难的事情。如果想使用头描述增加WITH HEADERS参数与SET p = row一类赋值即可。
红色部分才是文件内容哦
p.csv(pid,xm)
1,张三
2,李四
3,王五
4,赵六
o.csv(orgid,name)
1,公司1
2,公司2
3,公司3
4,公司4
r.csv(pid,orgid,type)
1,1,1
1,1,2
2,1,1
2,2,1
2,3,1
3,3,1
3,4,1
4,4,1
语句file:/r.csv文件目录实质是配置文件中的dbms.directories.import=import目录下,不支持随便指定目录,window版本需要在库文件所在位置创建import目录,而linux当前软件目录有import。
LOAD CSV FROM "file:/p.csv" AS row
CREATE (p:P{pid:row[0],xm:row[1]});
LOAD CSV FROM "file:/o.csv" AS row
CREATE (o:O{orgid:row[0],name:row[1]});
对没有索引的标签创建关系时必定死悄悄(测试几万节点无索引,创建关系就已经开始慢了),索引可凭空创建,也就是P\O不存在时也可以创建,后续不再需要对索引进行维护,有别于2.0版本。
CREATE INDEX ON :P(pid);
CREATE INDEX ON :O(orgid);
LOAD CSV FROM "file:/r.csv" AS row
MATCH (p:P),(o:O)
WHERE p.pid = row[0] and o.orgid=row[1]
CREATE (p)-[r:R{type:row[2]}]->(o);
如果嫌多个文件麻烦,也可以从一个文件进行导入,导入的同时增加节点与关系
LOAD CSV FROM "file:/r/0.csv" AS row
merge (p:P{pid:row[0]})
merge (o:O{orgid:row[1]})
CREATE unique (p)-[r:R{type:row[2]}]->(o);
neo4j-import方式
官网的开发手册中也有小例子,不过又是包含csv头的,且说多个文件,按照语法来说,至少有个两个文件,一个是节点,另外一个是关系数据。
把头和内容分离成两个文件
actors-h.csv
personId:ID,name
actors.csv
keanu,"Keanu Reeves"
laurence,"Laurence Fishburne"
carrieanne,"Carrie-Anne Moss"
movies-h.csv
movieId:ID,title,year:int
movies.csv
tt0133093,"The Matrix",1999
tt0234215,"The Matrix Reloaded",2003
tt0242653,"The Matrix Revolutions",2003
roles-h.csv
:START_ID,role,:END_ID
roles.csv
keanu,"Neo",tt0133093
keanu,"Neo",tt0234215
keanu,"Neo",tt0242653
laurence,"Morpheus",tt0133093
laurence,"Morpheus",tt0234215
laurence,"Morpheus",tt0242653
carrieanne,"Trinity",tt0133093
carrieanne,"Trinity",tt0234215
carrieanne,"Trinity",tt0242653
离线生成数据库,--nodes和--relationships都支持多文件写法,且认为是连续的文件,所以我们采用第一个文件只包含头的方式来解决问题。
rm -rf /root/hadoop/neo4j-community-3.1.3/data/databases/1.db
neo4j-import --into /root/hadoop/neo4j-community-3.1.3/data/databases/1.db --nodes:Movie /root/Desktop/movies-h.csv,/root/Desktop/movies.csv --nodes:Actor /root/Desktop/actors-h.csv,/root/Desktop/actors.csv --relationships:ACTED_IN /root/Desktop/roles-h.csv,/root/Desktop/roles.csv
傻瓜方式切换数据库(删除软链接最后不能加/)
rm -rf /root/hadoop/neo4j-community-3.1.3/data/databases/neo4j.db
ln -sf /root/hadoop/neo4j-community-3.1.3/data/databases/1.db /root/hadoop/neo4j-community-3.1.3/data/databases/neo4j.db
neo4j restart
import方式需要增加索引操作,否则严重影响查询效率。放开属性使其支持shell,考虑安全问题只开发127
dbms.shell.enabled=true
dbms.shell.host=127.0.0.1
dbms.shell.port=1337
创建索引文件index
CREATE INDEX ON :P(pid);
CREATE INDEX ON :O(orgid);
执行命令
neo4j-shell -file /xxxx/index
功能还是可以的,虽没想象中的那么强大,必经人家解决了一些数学问题,最短路径6级查询shortestPath系能稍微慢一些,但是也能理解。
说的简单勿喷
如何从hdfs导入多文件?再跟帖吧
补充内容 (2017-8-9 08:22):
目前我的做法是用2个MR计算出所需要的数据,用reduce(9)控制每个输出文件最多有9个,其中使用的分片MultipleOutputs,最后用命令下载这些文件,拼接成所需要的导入命令,因每个文件数量是固定的
补充内容 (2017-8-9 08:28):
导入头文件描述中是可以支持别名的写法
:ID(a)
:ID(b)
使用的时候
:START_ID(a)
:END_ID(b) |
|