neo4j 是图数据库中较为流行的一种,为了解决近期知识图谱工程项目的最后数据存储环节,在此测试 neo4j 的性能及可视化效果。

这里将会涉及:

  • Neo4j 在 red-hat 安装时 java 路径错误的解决
  • Neo4j 远程访问配置
  • Neo4j-Python 驱动测试

Neo4j 在 red-hat 环境配置的若干问题

因为 Neo4j 依赖 java, 所以先把 java 环境配置好;安装方法很多,主要有两种:

[root@ip-red-hat tmp]# yum install neo4j -y

- 官网下载zip包手动安装(略)
安装后可以直接启动:
```bash
neo4j console

如果不报错就可以再本地 lochalhost:7474 访问,安装时顺带有一个 web-browser 的模块,可以直接在浏览器看 UI 界面。

接下来就是我这边异常迷醉的 bug 了:java 路径错误。无论我怎么修改 $PATH 值,启动时还是报出一个错误的 java 的路径。我至今不知道他为什么不直接解析 $PATH 中的路径。要命的是 Google 了半天也没答案。。。

最后无奈,突然想起了还有个 JAVA_HOME 的东西,心想他是不是按照这个来读取路径的。。。

echo $JAVA_HOME

果然,是错误的路径,这个路径底下根本没有 java... 因为不是我的服务器,我也不知道先前的 JAVA_HOME 还被人配置了...

export JAVA_HOME=正确路径

然后可以启动了.

远程访问配置

neo4j 这么冷门的嘛,网上资料寥寥无几啊.... 这一步完全是凭经验做.

修改一下 /etc/neo4j/neo4j.conf

找到 HTTP-CONNECT 部分,改权限,IP,端口等等等。

本地访问效果:

上面的命令框可以直接输入 Cypher 脚本进行操作,就跟用 SQL 操作 RDB 一样

Python 驱动测试

# !/usr/bin/python 
# -*- coding: utf-8 -*- 


"""
create_author : jiangshouzhuang
create_time   : 2017-06-07
program       : *_* Read and Write Neo4j *_*
""" 

from neo4j.v1 import GraphDatabase 

class Neo4jHandler: 
   """
   Handler of graph database Neo4j reading and writing.
   """ 
   def __init__(self, driver): 
       """
       Get Neo4j server driver.
       :param driver: driver object
           A driver object holds the detail of a Neo4j database including serverURIs, credentials and other configuration, see
           " http://neo4j.com/docs/api/python-driver/current/driver.html".
       """ 
       self.driver = driver 

   def __repr__(self): 
       printer = 'o(>﹏<)o ......Neo4j old driver "{0}" carry me fly......o(^o^)o'.format(self.driver) 
       return printer 

   def listreader(self, cypher, keys): 
       """
       Read data from Neo4j in specified cypher.
       Read and parse data straightly from cypher field result.
       :param cypher: string
           Valid query cypher statement.
       :param keys: list
           Cypher query columns to return.
       :return: list
           Each returned record constructs a list and stored in a big list, [[...],[...], ...].
       """ 
       with self.driver.session() as session: 
           with session.begin_transaction() as tx: 
                data = [] 
                result = tx.run(cypher) 
                for record in result: 
                    rows = [] 
                    for key in keys: 
                        rows.append(record[key]) 
                    data.append(rows) 
                return data 

   def dictreader(self, cypher): 
       """
       Read data from Neo4j in specified cypher.
       The function depends on constructing dict method of dict(key = value) andany error may occur if the "key" is invalid to Python.
       you can choose function dictreaderopted() below to read data by hand(viathe args "keys").
       :param cypher: string
           Valid query cypher statement.
       :return: list
           Each returned record constructs a dict in "key : value" pairsand stored in a big list, [{...}, {...}, ...].
       """ 
       with self.driver.session() as session: 
           with session.begin_transaction() as tx: 
                data = [] 
                for record intx.run(cypher).records(): 
                    item = {} 
                    for args instr(record).split('>')[0].split()[1:]: 
                        exec"item.update(dict({0}))".format(args) 
                    data.append(item) 
                return data 

   def dictreaderopted(self, cypher, keys=None): 
       """
       Optimized function of dictreader().
       Read and parse data straightly from cypher field result.
        :param cypher: string
           Valid query cypher statement.
       :param keys: list, default : none(call dictreader())
           Cypher query columns to return.
       :return: list.
           Each returned record constructs an dict in "key : value" pairsand stored in a list, [{...}, {...}, ...].
       """ 
       if not keys: 
           return self.dictreader(cypher) 
       else: 
           with self.driver.session() as session: 
                with session.begin_transaction()as tx: 
                    data = [] 
                    result =tx.run(cypher) 
                    for record in result: 
                        item = {} 
                        for key in keys: 
                            item.update({key :record[key]}) 
                        data.append(item) 
                    return data 

   def cypherexecuter(self, cypher): 
       """
       Execute manipulation into Neo4j in specified cypher.
       :param cypher: string
           Valid handle cypher statement.
       :return: none.
       """ 
       with self.driver.session() as session: 
           with session.begin_transaction() as tx: 
                tx.run(cypher) 
        session.close() 


# self test 
if __name__ == "__main__": 
   uri = "bolt://192.168.1.11:7687" 
   driver = GraphDatabase.driver(uri, auth=("neo4j","zhangyun")) 
   MyNH = Neo4jHandler(driver) 
   print(MyNH) 
   cypher_exec = """
                    CREATE (Neo:Crew{name:'Neo'}),
                           (Morpheus:Crew{name: 'Morpheus'}),
                           (Trinity:Crew {name:'Trinity'}),
                           (Cypher:Crew:Matrix{name: 'Cypher'}),
                           (Smith:Matrix {name:'Agent Smith'}),
                           (Architect:Matrix{name:'The Architect'}),

                          (Neo)-[:KNOWS]->(Morpheus),
                          (Neo)-[:LOVES]->(Trinity),
                          (Morpheus)-[:KNOWS]->(Trinity),
                          (Morpheus)-[:KNOWS]->(Cypher),
                          (Cypher)-[:KNOWS]->(Smith),
                          (Smith)-[:CODED_BY]->(Architect)
                  """  # "example cypher statement fromhttp://console.neo4j.org/" 
   cypher_read = """
                    MATCH (a)-[:KNOWS|LOVES]-> (b:Crew {name: 'Trinity'})
                    RETURN a.name AS l, b.nameAS r
                  """ 
   MyNH.cypherexecuter(cypher_exec) 
   print(MyNH.listreader(cypher_read, ['l', 'r'])) 
   print(MyNH.dictreader(cypher_read)) 
print(MyNH.dictreaderopted(cypher_read,['l']))