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

Warming Up to Graphs

Warming Up to Graphs

From PyOhio 2014

Avatar for Brad Montgomery

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.