需求
现在有图数据,包含节点和边,节点或者关系都有大段的文本属性,并且需要对全文文本进行检索,因此计划使用Neo4j 进行关系存储以及图算法的应用,使用Elastic Search 进行全文搜索,因此需要Neo4j的数据与Elastic Search进行自动同步,从而实现节点/关系搜索使用Neo4j, 全文搜索使用Elastic Search, 各发挥自己的长处。
方案
正巧的Neo4j官方提供了一个插件neo-elasticsearch, 可以直接Neo4j的数据实时同步到ElasticSearch中。 不过由于官网文档的说明比较简单,以及本人对docker的熟练度有限,在使用docker搭建的过程中,遇到了很大的坑,记录于此。
环境如下:
- Ubuntu 16.04LST
- Docker 18.06.0-ce
- Neo4j:3.4
- ElasticSearch:6.4.2
安装ElasticSearch
ES的安装比较简单,直接按照官网说明 即可(2018.10当前版本号6.4.2)。 1
2docker run -p 9200:9200 -p 9300:9300 --name es \
-d -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:6.4.2es
,web端口为9200,在后台运行的的elastic search容器,可以访问http://ip:9200
查看
安装Neo4j及neo-elasticsearch插件
前面一篇博客Neo4j初探 已经提到了使用Docker安装Neo4j的启动失败的大坑,这里就不再赘述。因为在后续安装插件的时候,需要修改配置文件和拷贝插件,所以在新建neo4j容器的时候暴露出来conf和plugins目录,具体的命令如下: 1
2
3
4docker run -p 7474:7474 -p 7687:7687 -v $HOME/neo4j/data:/data \
-v $HOME/neo4j/conf:/var/lib/neo4j/conf \
-v $HOME/neo4j/plugins:/var/lib/neo4j/plugins \
--name neo4j --link es:es -d neo4j:3.4--link=es:es
表示neo4j这个容器依赖于es容器,可以使用docker ps
以及docker logs -f -t neo4j
查看运行状态和日志。 下面开始安装插件:
- 下载插件jar包: https://github.com/neo4j-contrib/neo4j-elasticsearch/releases 然后将jar包拷到
plugins
目录里面 - 修改配置文件(假设在Neo4j中有两类节点Person与Place):
1
2elasticsearch.host_name=http://es:9200
elasticsearch.index_spec=people:Person(first_name,last_name), places:Place(name) - 重启neo4j即可
docker restart neo4j
,可以通过日志来验证是否载入了docker exec neo4j cat /var/lib/neo4j/logs/debug.log | grep elastic
1
2
3396:2018-10-29 11:58:13.988+0000 INFO [o.n.k.i.DiagnosticsManager] elasticsearch.index_spec=people:Person(first_name,last_name), places:Place(name)
403:2018-10-29 11:58:13.989+0000 INFO [o.n.k.i.DiagnosticsManager] elasticsearch.host_name=http://es:9200
530:2018-10-29 11:58:14.023+0000 INFO [o.n.k.i.DiagnosticsManager] [classpath + loader.0] file:/var/lib/neo4j/plugins/neo4j-elasticsearch-3.4.5.jar
这里面有一点很关键的是host_name, 因为官方的文档是直接在主机搭建因此直接是localhost
, 但是在docker中两个容器是独立的ip,独立的服务,这里需要讲host_name改成上面创建elastic search容器的名称即es
, 这是因为在docker中,如果使用了--link
的话,docker会给当前容器内部写入一个连接容器的名字的环境变量。通过docker inspect
查看两个容器的ip地址,假设neo4j的ip为172.17.0.3
, es的ip为172.17.0.2
,这样docker会给neo4j注册一个名称为es,指向es容器的环境变量,因此需要这样填写:elasticsearch.host_name=http://es:9200
。
此外,elasticsearch.index_spec=people:Person(first_name,last_name), places:Place(name)
这条命令表示将neo4j中的Person节点存为es的people索引,Place节点存为places索引。
测试
首先使用neo4j新建节点: 1
CREATE (n:Person { first_name : "A", last_name: "Han" }) RETURN n;
当然修改,删除等操作都可以来实时同步到es。比较方便
当然也可以使用docker-compose
来同时集成两个容器, 附docker-compose.yml
:
1 | version: '2' |