2012-04-24

新手的 Neo4j + Python

因為我在公司使用 Ubuntu 11.10, 參考這一頁安裝時,需要留意一下... 不需要安裝 Neo4j community 1.7。 如果要安裝 neo4j-embedded 的話:
  1. 直接 sudo apt-get install python-jpype ,不用下載了。
  2. 如果一定要下載來自己編譯,可以用 sudo JAVA_HOME=/usr/lib/jvm/java-6-sun python setup.py install
  3. sudo apt-get install python-pip
  4. sudo pip install neo4j-embedded
就可以開始玩了... 網路上有好多 demo, 寫得好複雜的樣子,晚一點再來看有沒有簡單一點的。 啊。搞錯了。 用 neo4j-embedded 雖然沒什麼問題,但是公司的應用必須有 standalone server,而且把服務跑起來,才能用 browser,所以要安裝 neo4j-community:
  1. sudo ./neo4j-community-1.7/bin/neo4j install 安裝服務
  2. sudo -u neo4j /etc/init.d/neo4j-service start 把Neo4j打開
  3. 用瀏覽器看 http://localhost:7474/webadmin/
Python 可以用的 RESTful client 有兩個: neo4jrestclientpy2neo。 公司的 VM 上要安裝新軟體很痛苦,所以我本來應該裝 py2neo,可是因為 neo4jrestclient 包裝得和 neo4j-embedded 很像,所以下面的例子用的是 neo4jrestclient:
# 有名的 The Matrix 的例子
from neo4jrestclient.client import GraphDatabase
db = GraphDatabase("http://localhost:7474/db/data/")

thomas = db.node(name = 'Thomas Anderson', age = 29)
trinity = db.node(name = 'Trinity')
morpheus = db.node(name = 'Morpheus', rank = 'Captain', occupation = 'total badass')
cypher = db.node(name = 'Cypher', lastname = 'Reagan')
agentSmith = db.node(name = 'Agent Smith', version = '1.0b', language = 'C++')
architect = db.node(name = 'The Architect')
thomas.KNOWS(trinity)
trinity.LOVES(thomas, since = 'meeting the oracle')
thomas.KNOWS(morpheus)
trinity.KNOWS(cypher, since = 'a year before the movie', cooperatesOn = 'The Nebuchadnezzar')
cypher.KNOWS(agentSmith, disclosure = 'secret')
agentSmith.CODEDBY(architect)
搞定後,就可以用 python 命令列來玩耍:
>>> from neo4jrestclient.client import GraphDatabase
>>> gdb = GraphDatabase("http://localhost:7474/db/data/")
>>> n = gdb.node[5] # 假設 Trinity 是 node[5] 可以去 browser 看 :)
>>> n.relationships.all()[:]
[<Neo4j Relationship: http://localhost:7474/db/data/relationship/8>, <Neo4j Relationship: http://localhost:7474/db/data/relationship/5>, <Neo4j Relationship: http://localhost:7474/db/data/relationship/6>]
>>> n.relationships.all()[0].type
'KNOWS'
>>> n.relationships.all()[0].start
<Neo4j Node: http://localhost:7474/db/data/node/5>
>>> n.relationships.all()[0].end
<Neo4j Node: http://localhost:7474/db/data/node/7>
>>> n.relationships.all()[0].properties
{u'since': u'a year before the movie', u'cooperatesOn': u'The Nebuchadnezzar'}
然後是 traversals:
>>> from neo4jrestclient import client
>>> n.traverse(types=[client.All.KNOWS])[:]
[<Neo4j Node: http://localhost:7474/db/data/node/7>, <Neo4j Node: http://localhost:7474/db/data/node/4>]
>>> n.traverse(types=[client.Outgoing.KNOWS])[:]
[<Neo4j Node: http://localhost:7474/db/data/node/7>]
>>> n.traverse(types=[client.Incoming.KNOWS])[:]
[<Neo4j Node: http://localhost:7474/db/data/node/4>]
比方說想找 Trinity KNOWS 的人 KNOWS 的... (我為了舉例多加了一些關係)
# Ruby 寫起來好漂亮 T_T ==> me.outoging(:frienship).outgoing(:datingship)
>>> [n.traverse(types=[Outgoing.KNOWS])[:] for n in trinity.traverse(types=[Outgoing.KNOWS])[:]]
[[<Neo4j Node: http://127.0.0.1:7474/db/data/node/8>], [<Neo4j Node: http://127.0.0.1:7474/db/data/node/5>, <Neo4j Node: http://127.0.0.1:7474/db/data/node/4>]]
# 也可以接上 neo4j 的範例...
>>> gdb.traversal().relationships('KNOWS').traverse(trinity).nodes[:]
[<Neo4j Node: http://127.0.0.1:7474/db/data/node/7>, <Neo4j Node: http://127.0.0.1:7474/db/data/node/6>, <Neo4j Node: http://127.0.0.1:7474/db/data/node/4>]
# Incoming 和 Outgoing 直接偷偷用關鍵字...
>>> gdb.traversal().relationships('KNOWS', 'out').traverse(trinity).nodes[:]
[<Neo4j Node: http://127.0.0.1:7474/db/data/node/7>, <Neo4j Node: http://127.0.0.1:7474/db/data/node/6>]
>>> gdb.traversal().relationships('KNOWS', 'in').traverse(trinity).nodes[:]
[<Neo4j Node: http://127.0.0.1:7474/db/data/node/4>]

沒有留言: