Your SlideShare is downloading. ×
Introduction to py2neo
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Introduction to py2neo

11,238
views

Published on

An introduction to the python library py2neo, used for building applications which use the Neo4j graph database.

An introduction to the python library py2neo, used for building applications which use the Neo4j graph database.

Published in: Technology, News & Politics

1 Comment
8 Likes
Statistics
Notes
No Downloads
Views
Total Views
11,238
On Slideshare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
180
Comments
1
Likes
8
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Introducing py2neonigel@nigelsmall.name py2neo.org@technige @py2neo
  • 2. Me...
  • 3. Where does py2neo fit in? (your app) py2neo GET /db/data/ 200 OK REST Server Neo4j
  • 4. Coming Up...● Connecting & Creating● Property Containers● Indexes & Uniqueness● Cypher & Geoff● Installation● Future Plans
  • 5. Connecting & Creating
  • 6. Default Connections>>> from py2neo import neo4j>>> graph_db = neo4j.GraphDatabaseService() default connection is made to <http://localhost:7474/db/data/>
  • 7. Custom Connections>>> from py2neo import neo4j>>> uri = "http://otherserv:9999/db/data/">>> graph_db = neo4j.GraphDatabaseService(uri)>>> graph_db.neo4j_version(1, 8, uM04, 1, ug892e348)
  • 8. A few simple methods...>>> graph_db.get_node(0)Node(http://localhost:7474/db/data/node/0)>>> graph_db.get_reference_node()Node(http://localhost:7474/db/data/node/0)>>> graph_db.get_node_count()1>>> graph_db.get_relationship_count()0
  • 9. Sample data: a family tree m (1947) Phil (1921) Liz (1926) Chaz (1948) Anne (1950) Andy (1960) Ed (1964)All characters appearing in this work are fictitious. Any resemblance to real persons, living or dead, is purely coincidental.
  • 10. list of nodes createnodes = graph_db.create( Phil Liz {"name": "Phil", "born": 1921}, {"name": "Liz", "born": 1926}, {"name": "Chaz", "born": 1948}, {"name": "Anne", "born": 1950}, Chaz Anne {"name": "Andy", "born": 1960}, {"name": "Ed", "born": 1964},) Andy Ed
  • 11. list of relationships create MARRIEDrels = graph_db.create( Phil Liz (phil, "MARRIED", liz), (chaz, "FATHER", phil), FATHER MOTHER (chaz, "MOTHER", liz), Chaz) node must already exist
  • 12. createfamily = graph_db.create( {"name": "Phil", "born": 1921}, {"name": "Liz", "born": 1926}, {"name": "Chaz", "born": 1948}, {"name": "Anne", "born": 1950}, {"name": "Andy", "born": 1960}, {"name": "Ed", "born": 1964}, (0, "MARRIED", 1, {"year": 1947, "place": "London"}), (2, "FATHER", 0), (3, "FATHER", 0), (4, "FATHER", 0), (5, "FATHER", 0), (2, "MOTHER", 1), (3, "MOTHER", 1), (4, "MOTHER", 1), (5, "MOTHER", 1),)
  • 13. list of nodes and relationships createfamily = graph_db.create( {"name": "Phil", "born": 1921}, {"name": "Liz", "born": 1926}, {"name": "Chaz", "born": 1948}, {"name": "Anne", "born": 1950}, {"name": "Andy", "born": 1960}, {"name": "Ed", "born": 1964}, (0, "MARRIED", 1, {"year": 1947, "place": "London"}), (2, "FATHER", 0), (3, "FATHER", 0), relationship (4, "FATHER", 0), (5, "FATHER", 0), properties (2, "MOTHER", 1), (3, "MOTHER", 1), (4, "MOTHER", 1), (5, "MOTHER", 1),) node defined in same batchnodes, rels = family[0:6], family[6:]phil, liz, chaz, anne, andy, ed = nodes
  • 14. Property Containers
  • 15. neo4j.PropertyContainer PropertyContainer Node Relationship
  • 16. PropertyContainers implement many of the container methods defined by the Python standard<http://docs.python.org/reference/datamodel.html#emulating-container-types>
  • 17. neo4j.PropertyContainer set property# update propertiesliz["star_sign"] = "Taurus"# query properties get property test propertyfor node in nodes: containment name = node["name"] if "star_sign" in node: print name + " is a node["star_sign"] else: print name + " doesnt believe in horoscopes"
  • 18. neo4j.Node PropertyContainerNode Relationship
  • 19. Relationships and Related Nodes Chazparental_rels = liz.get_relationships( Liz neo4j.Direction.INCOMING, "MOTHER" Anne) Chazparental_rels = liz.get_relationships_with( Liz chaz, neo4j.Direction.INCOMING, "MOTHER" Anne) Chazchildren = liz.get_related_nodes( Liz neo4j.Direction.INCOMING, "MOTHER" Anne)
  • 20. Relationships and Related Nodes>>> liz.has_relationship(neo4j.Direction.BOTH, "MARRIED")True>>> anne.is_related_to(phil, neo4j.Direction.OUTGOING, "FATHER")True>>> ed.is_related_to(andy, neo4j.Direction.BOTH, "BROTHER")False could also specify multiple types
  • 21. neo4j.Relationship PropertyContainerNode Relationship
  • 22. neo4j.Relationship>>> rels[0].start_nodeNode(http://localhost:7474/db/data/node/1)>>> rels[0].end_nodeNode(http://localhost:7474/db/data/node/2)>>> rels[0].typeMARRIED
  • 23. More sample data: a second tree m George (1895) Betty (1900) Liz (1926) Maggie (1930)
  • 24. m George (1895) Betty (1900) Liz (1926) Maggie (1930) m (1947) Phil (1921) Liz (1926)Chaz (1948) Anne (1950) Andy (1960) Ed (1964)
  • 25. m George (1895) Betty (1900) same person Liz (1926) Maggie (1930) m (1947) Phil (1921) Liz (1926)Chaz (1948) Anne (1950) Andy (1960) Ed (1964)
  • 26. How can we avoidduplicate nodes?
  • 27. Indexes
  • 28. Indexing the first family...>>> people = graph_db.get_or_create_index(neo4j.Node, "People")>>> for node in nodes:... people.add("name", node["name"], node)>>> people.get("name", "Liz")[Node(http://localhost:7474/db/data/node/2)] list of matching entities
  • 29. ...and the second>>> new_props = [... {"name": "George", "born": 1895},... {"name": "Betty", "born": 1900},... {"name": "Liz", "born": 1926},... {"name": "Maggie", "born": 1930},... ]>>> george, betty, liz, maggie = [... people.get_or_create("name", prop["name"], prop)... for prop in new_props same node... ] as before>>> people.get("name", "Liz")[Node(http://localhost:7474/db/data/node/2)]
  • 30. A Quick Query>>> people.query("name:*e*")[Node(http://localhost:7474/db/data/node/4),Node(http://localhost:7474/db/data/node/7),Node(http://localhost:7474/db/data/node/8),Node(http://localhost:7474/db/data/node/9)] People George name Andy name Anne Maggie name Betty name Chaz name Ed name George Anne name Liz name Maggie Betty name Phil
  • 31. Weve added thenodes... what about the relationships?
  • 32. Cypher & Geoff
  • 33. Cypher RELATESTART a=node(1), b=node(2)RELATE (a)-[ab:KNOWS]->(b)RETURN ab
  • 34. Cypher RELATEa b RELATE a ba b RELATE a b !a b RELATE
  • 35. relatenew_rels = graph_db.relate( (george, "MARRIED", betty), (liz, "FATHER", george), (maggie, "FATHER", george), (liz, "MOTHER", betty), (maggie, "MOTHER", betty), George MARRIED Betty) FATHER FATHER MOTHER MOTHER Liz Maggie
  • 36. For relationships,relate can be seen as an idempotent alternative to create
  • 37. cypher.execute>>> from py2neo import cypher>>> query = "START q=node(1) RETURN q">>> data, metadata = cypher.execute(graph_db, query)>>> for row in data:... q = row[0]... print q first column
  • 38. cypher.execute>>> from py2neo import cypher>>> query = "START q=node(1) RETURN q">>> data, metadata = cypher.execute(graph_db, query) available only after all rows received>>> for row in data:... q = row[0]... print q first column
  • 39. cypher.executequery = "START q=node(1) RETURN q" executed once per row as eachdef print_row(row): row is received q = row[0] print rowcypher.execute(graph_db, query, row_handler=print_row)
  • 40. Command Line Cypherelgin@forge:~% cypher "start a=node(1) match (a)-[:MARRIED]->(b) return a, b"+------------------------------------------------------------------+| a | b |+------------------------------------------------------------------+| (1) {"name":"Phil","born":1921} | (2) {"name":"Liz","born":1926} |+------------------------------------------------------------------+elgin@forge:~% cypher -f csv "start a=node(1) match (a)-[ab:MARRIED]->(b) return a, ab, b""a","ab","b""(1)","(1)-[0:MARRIED]->(2)","(2)"elgin@forge:~% cypher -f json "start a=node(1) match (a)-[ab:MARRIED]->(b) return a, ab, b"[ {"a": "(1)", "ab": "(1)-[0:MARRIED]->(2)", "b": "(2)"}]elgin@forge:~% cypher -f geoff "start a=node(1) match (a)-[ab:MARRIED]->(b) return a, ab, b"(1) {"name": "Phil", "born": 1921}(2) {"name": "Liz", "born": 1926}(1)-[0:MARRIED]->(2) {"year": 1947, "place": "London"}
  • 41. Geoff is to graph data asCSV is to tabular data <http://geoff.nigelsmall.net/>
  • 42. elgin@forge:~% cypher -f geoff "start n=node(*), r=rel(*) return n, r"(0) {}(1) {"born": 1921, "name": "Phil", "family": "Windsor"}(2) {"born": 1926, "star_sign": "Taurus", "family": "Windsor", "name": "Liz"}(3) {"born": 1948, "name": "Chaz", "family": "Windsor"}(4) {"born": 1950, "name": "Anne", "family": "Windsor"}(5) {"born": 1960, "name": "Andy", "family": "Windsor"}(6) {"born": 1964, "name": "Ed", "family": "Windsor"}(7) {"born": 1895, "name": "George"}(8) {"born": 1900, "name": "Betty"}(9) {"born": 1930, "name": "Maggie"}(1)-[0:MARRIED]->(2) {"place": "London", "year": 1947}(3)-[1:FATHER]->(1) {}(4)-[2:FATHER]->(1) {}(5)-[3:FATHER]->(1) {}(6)-[4:FATHER]->(1) {}(3)-[5:MOTHER]->(2) {}(4)-[6:MOTHER]->(2) {}(5)-[7:MOTHER]->(2) {}(6)-[8:MOTHER]->(2) {}(7)-[9:MARRIED]->(8) {}(2)-[10:FATHER]->(7) {}(9)-[11:FATHER]->(7) {}(2)-[12:MOTHER]->(8) {}(9)-[13:MOTHER]->(8) {}
  • 43. Neo4j Console
  • 44. Installation
  • 45. Requirements● Python 2.6+ <http://python.org/>● Tornado 2.2.1 <http://www.tornadoweb.org/>● Neo4j 1.6+ <http://neo4j.org/>
  • 46. Installation <http://pypi.python.org/pypi/py2neo>elgin@forge:~% sudo pip install py2neoelgin@forge:~% sudo pip install --upgrade py2neo
  • 47. Source Code <https://github.com/nigelsmall/py2neo>elgin@forge:~% git clone git@github.com:nigelsmall/py2neo.git
  • 48. Future Plans● Fast HTTP● Multi-threading support● Python 3● Command line tools● Property caching● Test harness for multiple Neo4j versions● New methods, e.g. get_paths_to
  • 49. EOFnigel@nigelsmall.name py2neo.org@technige @py2neo