Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Warming Up to Graphs

Warming Up to Graphs

From PyOhio 2014

Brad Montgomery

July 27, 2014
Tweet

More Decks by Brad Montgomery

Other Decks in Technology

Transcript

  1. Neo4j • Commercial Software • Community Edition is Open Source

    (GPL/AGPL) • Written in Java • Has a RESTful API • ACID/Transactions/High Availability* • Supports Billions of Nodes & Relationships on a single machine.
  2. How to play with Neo4j 1. Download the current version

    (2.1.2) 2. Unpack the .tar.gz file. 3. Install Java? 4. ./neo4j-community-2.1.2/bin/neo4j start 5. Visit http://localhost:7474/
  3. Modeling Data User! name: Janet email: [email protected] Project! name: open-unicorn

    website: open-unicorn.org Edges are called “Relationships”
  4. Modeling Data User! name: Janet email: [email protected] Project! name: open-unicorn

    website: open-unicorn.org CONTRIBUTES_TO ! first_commit: 2014-07-27 User! name: Rose email: [email protected] OWNED_BY
  5. from py2neo import neo4j! ! # Connect to a DB.!

    db = neo4j.GraphDatabaseService(! ‘http://localhost:7474/db/data/'! )
  6. from py2neo import node! ! # Create a Node! n

    = node(name="Janet", email="[email protected]")! Properties
  7. from py2neo import node! ! # Create a Node! n

    = node(name="Janet", email="[email protected]")! An Abstract Node
  8. from py2neo import node, rel! ! # Create some Users!

    user_data = [{'name': 'Janet', 'email': '[email protected]'}]! user_nodes = [node(d) for d in user_data] # Abstract Nodes! users = db.create(*user_nodes)! ! ! ! !
  9. from py2neo import node, rel! ! # Create some Users!

    user_data = [{'name': 'Janet', 'email': '[email protected]'}]! user_nodes = [node(d) for d in user_data] # Abstract Nodes! users = db.create(*user_nodes)! ! for u in users:! u.add_labels("User")! ! Now you can add Labels
  10. from py2neo import node, rel! ! # Create some Projects.!

    project_data = [! {'name': 'open-unicorn', 'website': 'open-unicorn.org'}! ]! project_nodes = [node(d) for d in project_data]! projects = db.create(*project_nodes)! ! # Every User contributes to every Project.! rels = []! for p in projects:! p.add_labels("Project")! for u in users:! rels.append(! rel(u, "CONTRIBUTES_TO", p)! )! ! # Save the relationships! relationships = db.create(*rels)!
  11. # Find a User based on their email! users =

    db.find(! “User",! property_key=“email",! property_value=“[email protected]"! )! ! print(users[0])! # (1 {'name': ‘Janet',! ‘email': '[email protected]'})!
  12. # Find a User based on their email! users =

    db.find(! “User",! property_key=“email",! property_value=“[email protected]"! )! ! print(users[0])! # (1 {'name': ‘Janet',! ‘email': '[email protected]'})! Label
  13. # Find a User based on their email! users =

    db.find(! “User",! property_key=“email",! property_value=“[email protected]"! )! ! print(users[0])! # (1 {'name': ‘Janet',! ‘email': '[email protected]'})! Nodes get an ID, but don’t rely on it.
  14. # Access Labels and additional properties! print user.get_labels()! # {'User'}!

    ! print user.get_properties()! # {'name': 'Janet', 'email': '[email protected]'}
  15. # Accessing Relationships! for relationship in user.match_outgoing():! print(! relationship.type, !

    relationship.end_node[‘name']! )! # CONTRIBUTES_TO open-unicorn!
  16. # Accessing Relationships! for relationship in user.match_outgoing():! print(! relationship.type, !

    relationship.end_node[‘name']! )! # CONTRIBUTES_TO open-unicorn! User Project
  17. # Find a project's contributors.! # 1) get the project

    node! projects = db.find(! "Project",! property_key="name",! property_value="open-unicorn"! )! p = projects[0]! ! # 2) list all contributors! for r in p.match_incoming(rel_type="CONTRIBUTES_TO"):! print(rel.start_node['name']) # Janet!
  18. More Interesting Queries • People that contribute to open-unicorn also

    contribute to … ? • Who contributes to similar projects as me? • Six degrees of Guido van Rossum?
  19. from py2neo import cypher! ! # Create a Transaction.! session

    = cypher.Session(! ‘http://localhost:7474/db/data/'! )! tx = session.create_transaction()
  20. query = """! MATCH (n:User) ! WHERE n.username={name} ! RETURN

    n! """! tx.append(! query,! parameters={‘name’:‘Janet’}! )! results = tx.commit()
  21. query = """! MATCH (n:User) ! WHERE n.username={name} ! RETURN

    n! """! tx.append(! query,! parameters={‘name’:‘Janet’}! )! results = tx.commit() Parameter Substitution
  22. # Returns a list of Records for each query.! [!

    [! Record(! columns=('n',),! values=(Node(), )! )! ],! ]!
  23. # Returns a list of Records for each query.! [!

    [! Record(! columns=('n',),! values=(Node(), )! )! ],! ]! May contain Nodes and Relationships
  24. query = """! MATCH! (p:project)<-[:CONTRIBUTES_TO]-(u:user)! -[:CONTRIBUTES_TO]->(o:project)! WHERE p.name={name}! RETURN o.name,

    count(*)! ORDER BY count(*) DESC, o.name! LIMIT {limit}! """! # tx is a transaction object! tx.append(! query,! parameters={"name": "open-unicorn", "limit": 5}! )! results = tx.commit()! for record in results[0]:! name, count = record.values! print("({0}) {1}".format(count, name))!
  25. # o.name count(*)! # --------------------------! # open-jackrabbit 6! # flailing-jackrabbit

    5! # secret-butterfly 5! # tiny-armyant 5! # flaming-butterfly 3
  26. # People who contribute to similar projects as Janet! query

    = """! MATCH! (a:user)-[:CONTRIBUTES_TO]->(p:project)! -[:OWNED_BY]->(u)! -[:CONTRIBUTES_TO]->(x:project)! <-[:CONTRIBUTES_TO]-(people)! WHERE a.username={name} AND NOT a=people! RETURN people.name AS name, count(*) AS similar_contribs! ORDER BY similar_contribs DESC! """! # tx is a transaction object! tx.append(! query,! parameters={"name":"Janet", "limit": 5}! )! results = tx.commit()! for record in results[0]:! name, count = record.values! print("{0} {1}".format(name, count))
  27. # people.name count(*)! # ---------------------------! # Bridget Betty 33! #

    Donald Catherine 33! # Donald Bob 30! # Frank Chuck 28! # Bob Brad 27
  28. # Path between two Users! query = """! MATCH! (a:user),

    (b:user),! p=shortestPath((a)-[]->(b))! WHERE a.name={name_a} AND b.name={name_b}! RETURN LENGTH(p), p! """! params = {'name_a': 'Janet' 'name_b': 'Daisy'}! tx.append(query, parameters=params)! results = tx.commit()! for record in results[0]:! length, path = record.values! print("{0} hops".format(length))! for rel in path.relationships:! print("({0})-[:{1}]->({2})".format(! rel.start_node['name'],! rel.type,! rel.end_node['name']! ))
  29. # 6 hops.! # (Janet)-[:CONTRIBUTES_TO]->(enterprise-grasshopper)! # (enterprise-grasshopper)-[:OWNED_BY]->(Zoe)! # (Zoe)-[:CONTRIBUTES_TO]->(open-turtledove)! #

    (open-turtledove)-[:OWNED_BY]->(Delia)! # (Delia)-[:CONTRIBUTES_TO]->(flailing-sealion)! # (flailing-sealion)-[:OWNED_BY]->(Daisy)!
  30. ! class User(object):! ! def __init__(self, name=None, email=None):! self.name =

    name! self.email = email! ! ! class Project(object):! ! def __init__(self, name=None):! self.name = name!
  31. from py2neo import ogm! ! # Create a User &

    Project! store = ogm.Store(db)! u = User("Janet", "[email protected]")! p = Project(“open-unicorn")! ! store.save_unique("User", "email", u.email, u)! store.save_unique("project", "name", p.name, p)! store.relate(u, ”CONTRIBUTES_TO”, p)! store.save(u)!
  32. # Retrieve a User! store = ogm.Store(db)! u = store.load_unique(!

    "User", "email","[email protected]", User! )! p = store.load_unique(! "Project", "name", "massive-aardvark", Project! )! ! # Get some relationships! contribs = store.load_related(! u, "CONTRIBUTES_TO", Project! )!
  33. More Python • Neomodel - Neo4j Models for Django (build

    on py2neo) • neo4django - Neo4j Models for Django • bulbflow - Neo4j, OrientDB, Titan • neo4j-rest-client - Nice API. Active development. • py2neo - Undergoing a major rewrite.